Short rot13 function - Python

I am looking for the short and cool rot13 function in Python ;-) I wrote this function:

def rot13(s): chars = "abcdefghijklmnopqrstuvwxyz" trans = chars[13:]+chars[:13] rot_char = lambda c: trans[chars.find(c)] if chars.find(c)>-1 else c return ''.join( rot_char(c) for c in s ) 

Can anyone do this better? For example, support for uppercase characters.

+52
python string encoding
Jul 17 '10 at 0:33
source share
20 answers

Here is maketrans / translate solution

 import string rot13 = string.maketrans( "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm") string.translate("Hello World!", rot13) # 'Uryyb Jbeyq!' 
+66
Jul 17 2018-10-17T00:
source share

It is very simple:

 >>> import codecs >>> codecs.encode('foobar', 'rot_13') 'sbbone' 
+104
Jul 17 '10 at 4:27
source share
 >>> 'foobar'.encode('rot13') 'sbbone' 

(I heard rumors that this does not work in Python 3.x.)

+61
Jul 17 '10 at 0:37
source share

maketrans and translate functions in the string module are convenient for this type of thing. Of course, the encode method in the amber response is even more efficient for this particular case.

Here's a general solution:

 import string def make_rot_n(n): lc = string.ascii_lowercase uc = string.ascii_uppercase trans = string.maketrans(lc + uc, lc[n:] + lc[:n] + uc[n:] + uc[:n]) return lambda s: string.translate(s, trans) rot13 = make_rot_n(13) rot13('foobar') # 'sbbone' 
+21
Jul 17 2018-10-17T00:
source share

From the module this.py ( import this ).

 d = {} for c in (65, 97): for i in range(26): d[chr(i+c)] = chr((i+13) % 26 + c) print "".join([d.get(c, c) for c in s]) 
+10
Jul 20 '10 at 16:30
source share

As with Python 3.1, string.translate and string.maketrans no longer exist. However, these methods can be used instead of bytes .

Thus, the modern solution, directly inspired by Pavel Rubel, is as follows:

 rot13 = bytes.maketrans( b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", b"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM") b'Hello world!'.translate(rot13) 

Conversion from string to bytes and vice versa can be done using the encode and decode built-in functions.

+8
May 01 '12 at 10:34
source share

Try the following:

 import codecs codecs.encode("text to be rot13()'ed", "rot_13") 
+5
Jul 17 '10 at 0:40
source share

In python-3, str -codec mentioned above is listed in the standard codecs library:

 > import codecs > codecs.encode('foo', 'rot13') sbb 
+4
Aug 04 '15 at 19:31
source share

For arbitrary values, something like this works for 2.x

 from string import ascii_uppercase as uc, ascii_lowercase as lc, maketrans rotate = 13 # ROT13 rot = "".join([(x[:rotate][::-1] + x[rotate:][::-1])[::-1] for x in (uc,lc)]) def rot_func(text, encode=True): ascii = uc + lc src, trg = (ascii, rot) if encode else (rot, ascii) trans = maketrans(src, trg) return text.translate(trans) text = "Text to ROT{}".format(rotate) encode = rot_func(text) decode = rot_func(encode, False) 
+2
Jul 22 '12 at 9:14
source share

This works for uppercase and lowercase letters. I do not know how elegant you are.

 def rot13(s): rot=lambda x:chr(ord(x)+13) if chr(ord(x.lower())+13).isalpha()==True else chr(ord(x)-13) s=[rot(i) for i in filter(lambda x:x!=',',map(str,s))] return ''.join(s) 
+2
Aug 24 2018-12-12T00:
source share

You can maintain capital letters of the source code sent by Mr. Walter, alternating upper case letters with lower case letters.

 chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" 

If you notice that the capitalized index is all even numbers, and the lowercase index is odd.

  • A = 0 a = 1,
  • B = 2, b = 3,
  • C = 4, c = 4,
  • ...

This odd pattern allows us to safely add the required amount without worrying about the case.

 trans = chars[26:] + chars[:26] 

The reason you add 26 is because the string is doubled with letters due to uppercase letters. However, a shift of another 13 spaces in the alphabet.

Full code:

 def rot13(s): chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" trans = chars[26:]+chars[:26] rot_char = lambda c: trans[chars.find(c)] if chars.find(c) > -1 else c return ''.join(rot_char(c) for c in s) 

OUTPUT (Tested with python 2.7):

 print rot13("Hello World!") --> Uryyb Jbeyq! 
+2
Dec 26 '13 at 4:02
source share

The next function rot(s, n) encodes a string s encoded with ROT- n for any integer n , with n being the default of 13. Both upper and lower case letters are supported. Values n greater than 26 or negative values ​​are processed accordingly, for example, a shift of 27 positions is equal to a shift of one position. Decoding is performed using invrot(s, n) .

 import string def rot(s, n=13): '''Encode string s with ROT-n, ie, by shifting all letters n positions. When n is not supplied, ROT-13 encoding is assumed. ''' upper = string.ascii_uppercase lower = string.ascii_lowercase upper_start = ord(upper[0]) lower_start = ord(lower[0]) out = '' for letter in s: if letter in upper: out += chr(upper_start + (ord(letter) - upper_start + n) % 26) elif letter in lower: out += chr(lower_start + (ord(letter) - lower_start + n) % 26) else: out += letter return(out) def invrot(s, n=13): '''Decode a string s encoded with ROT-n-encoding When n is not supplied, ROT-13 is assumed. ''' return(rot(s, -n)) 
+2
Jun 22 '15 at 11:51
source share

Single line to rot13 line S :

 S.translate({a : a + (lambda x: 1 if x>=0 else -1)(77 - a) * 13 for a in range(65, 91)}) 
+2
Feb 20 '16 at 7:19
source share
 def rot13(s): lower_chars = ''.join(chr(c) for c in range (97,123)) #ASCII az upper_chars = ''.join(chr(c) for c in range (65,91)) #ASCII AZ lower_encode = lower_chars[13:] + lower_chars[:13] #shift 13 bytes upper_encode = upper_chars[13:] + upper_chars[:13] #shift 13 bytes output = "" #outputstring for c in s: if c in lower_chars: output = output + lower_encode[lower_chars.find(c)] elif c in upper_chars: output = output + upper_encode[upper_chars.find(c)] else: output = output + c return output 

Another solution with switching. Perhaps this code helps other people better understand rot13. Did not test it completely.

+1
Sep 25 '13 at 23:26
source share
 from string import maketrans, lowercase, uppercase def rot13(message): lower = maketrans(lowercase, lowercase[13:] + lowercase[:13]) upper = maketrans(uppercase, uppercase[13:] + uppercase[:13]) return message.translate(lower).translate(upper) 
0
Feb 13 '15 at 19:44
source share

Interesting exercises ;-) I think I have a better solution, because:

  • no modules needed, uses only built-in functions -> without obsolescence
  • It can be used as one liner.
  • based on ascii, no dicts / string mapping, etc.

Python 2 and 3 (possibly Python 1):

 def rot13(s): return ''.join([chr(ord(n) + (13 if 'Z' < n < 'n' or n < 'N' else -13)) if n.isalpha() else n for n in s]) def rot13_verbose(s): x = [] for n in s: if n.isalpha(): # 'n' is the 14th character in the alphabet so if a character is bigger we can subtract 13 to get rot13 ort = 13 if 'Z' < n < 'n' or n < 'N' else -13 x.append(chr(ord(n) + ort)) else: x.append(n) return ''.join(x) # crazy .min version (99 characters) disclaimer: not pep8 compatible^ def r(s):return''.join([chr(ord(n)+(13if'Z'<n<'n'or'N'>n else-13))if n.isalpha()else n for n in s]) 
0
Apr 09 '15 at 9:43 on
source share

I found this post when I became interested in the easiest way to implement rot13 in Python. My goals:

  • Works on both Python 2.7.6 and 3.3.
  • Handle both uppercase and lowercase.
  • Do not use external libraries.

This meets all three of these requirements. That being said, I'm sure that he has not won a single code golf competition.

 def rot13(string): CLEAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' ROT13 = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm' TABLE = {x: y for x, y in zip(CLEAR, ROT13)} return ''.join(map(lambda x: TABLE.get(x, x), string)) if __name__ == '__main__': CLEAR = 'Hello, World!' R13 = 'Uryyb, Jbeyq!' r13 = rot13(CLEAR) assert r13 == R13 clear = rot13(r13) assert clear == CLEAR 

This works by creating a lookup table and simply returning the original character for any character not found in the lookup table.

Update

I need to worry that someone wants to use this to encrypt an arbitrarily large file (say, a few gigabytes of text). I don’t know why they want to do it, but what if they do it? So I rewrote it as a generator. Again, this was tested in both Python 2.7.6 and 3.3.

 def rot13(clear): CLEAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' ROT13 = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm' TABLE = {x: y for x, y in zip(CLEAR, ROT13)} for c in clear: yield TABLE.get(c, c) if __name__ == '__main__': CLEAR = 'Hello, World!' R13 = 'Uryyb, Jbeyq!' r13 = ''.join(rot13(CLEAR)) assert r13 == R13 clear = ''.join(rot13(r13)) assert clear == CLEAR 
0
Jun 19 '15 at 15:41
source share

You can also use this as well.

 def n3bu1A(n): o="" key = { 'a':'n', 'b':'o', 'c':'p', 'd':'q', 'e':'r', 'f':'s', 'g':'t', 'h':'u', 'i':'v', 'j':'w', 'k':'x', 'l':'y', 'm':'z', 'n':'a', 'o':'b', 'p':'c', 'q':'d', 'r':'e', 's':'f', 't':'g', 'u':'h', 'v':'i', 'w':'j', 'x':'k', 'y':'l', 'z':'m', 'A':'N', 'B':'O', 'C':'P', 'D':'Q', 'E':'R', 'F':'S', 'G':'T', 'H':'U', 'I':'V', 'J':'W', 'K':'X', 'L':'Y', 'M':'Z', 'N':'A', 'O':'B', 'P':'C', 'Q':'D', 'R':'E', 'S':'F', 'T':'G', 'U':'H', 'V':'I', 'W':'J', 'X':'K', 'Y':'L', 'Z':'M'} for x in n: v = x in key.keys() if v == True: o += (key[x]) else: o += x return o Yes = n3bu1A("N zhpu fvzcyre jnl gb fnl Guvf vf zl Zragbe!!") print(Yes) 
0
Aug 19 '15 at 18:31
source share

I could not leave this question here without a single statement using the modulo operator.

 def rot13(s): return ''.join([chr(x.islower() and ((ord(x) - 84) % 26) + 97 or x.isupper() and ((ord(x) - 52) % 26) + 65 or ord(x)) for x in s]) 

It is not pythonic nor good practice, but it works!

 >> rot13("Hello World!") Uryyb Jbeyq! 
0
Feb 20 '16 at 14:02
source share

Short decision:

 def rot13(text): return "".join([x if ord(x) not in range(65, 91)+range(97, 123) else chr(((ord(x)-97+13)%26)+97) if x.islower() else chr(((ord(x)-65+13)%26)+65) for x in text]) 
-2
Apr 19 '16 at 10:11
source share



All Articles