Short rot13 function - Python

121,827

Solution 1

maketrans()/translate() solutions…

Python 2.x

import string
rot13 = string.maketrans( 
    "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", 
    "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
string.translate("Hello World!", rot13)
# 'Uryyb Jbeyq!'

Python 3.x

rot13 = str.maketrans(
    'ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz',
    'NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm')
'Hello World!'.translate(rot13)
# 'Uryyb Jbeyq!'

Solution 2

It's very simple:

>>> import codecs
>>> codecs.encode('foobar', 'rot_13')
'sbbone'

Solution 3

This works on Python 2 (but not Python 3):

>>> 'foobar'.encode('rot13')
'sbbone'

Solution 4

The maketrans and translate methods of str are handy for this type of thing.

Here's a general solution:

import string

def make_rot_n(n):
    lc = string.ascii_lowercase
    uc = string.ascii_uppercase
    trans = str.maketrans(lc + uc,
                          lc[n:] + lc[:n] + uc[n:] + uc[:n])
    return lambda s: str.translate(s, trans)

rot13 = make_rot_n(13)

rot13('foobar')
# 'sbbone'

Solution 5

From the builtin module this.py (import this):

s = "foobar"

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]))  # sbbone
Share:
121,827
svenwltr
Author by

svenwltr

I like production being up.

Updated on July 05, 2022

Comments

  • svenwltr
    svenwltr almost 2 years

    I am searching for a short and cool rot13 function in Python ;-) I've written 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 make it better? E.g supporting uppercase characters.

  • Amber
    Amber almost 14 years
    The .encode method is included as part of string objects and doesn't need to be specifically imported.
  • svenwltr
    svenwltr almost 14 years
    This is the shortest and its available under 3.0 :-)
  • Youarefunny
    Youarefunny about 13 years
    This appears to be the new proper way to do it. They moved it out of the string object for modularity. Now the string object str.encode() raises errors about not returning a byte array or bytes object.
  • Admin
    Admin almost 11 years
    But in Python 3, you need to spell it "rot_13" or "rot-13", not "rot13". I edited the answer.
  • Wooble
    Wooble over 10 years
    This no longer works on Python3.2+; maketrans was removed from the string module. Use Nazmul Hasan's codecs answer instead.
  • Milo P
    Milo P about 10 years
    Note also that this causes problems if you're trying to make Unicode text into rot13 and it contains any character larger than one byte (e.g., a non-breaking space).
  • Jonathan Potter
    Jonathan Potter over 8 years
    This doesn't work in Python 3, but @Nazmul's similar method does.
  • kkessell
    kkessell over 8 years
    Rumor: that's possibly just rot13 reading of a file as python source. See stackoverflow.com/a/1024693/26494
  • Muposat
    Muposat almost 8 years
    for Python3.x: change to rot13 = str.maketrans(...) and then "Hello World!".translate(rot13)
  • ankostis
    ankostis over 7 years
    @steven-rumbalski Strange! In py3.5 I get this error: LookupError: 'rot13' is not a text encoding; use codecs.encode() to handle arbitrary codecs
  • Brent Knox
    Brent Knox over 7 years
    for Python3.x import string rot13 = str.maketrans( "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm") print(str.translate("Hello World!", rot13))
  • wjandrea
    wjandrea about 7 years
    Doug's answer has a cleaner way of making a dict.
  • 김민준
    김민준 almost 7 years
    You can also directly import this. import this;rot13 = lambda s:''.join(this.d.get(c, c) for c in s). Just saying.
  • Martijn Pieters
    Martijn Pieters over 6 years
    @poke: it is definitely an available codec in Python 3. Just not as a str-to-bytes or bytes-to-str codec.
  • Martijn Pieters
    Martijn Pieters over 6 years
    @Amber: str.encode() can only produce bytes in Python 3. The rot13 codec is a str-to-str codec and is only available via codecs.encode() and codecs.decode().
  • Martijn Pieters
    Martijn Pieters over 6 years
    @user1220978: rot13 is available in 3.6 at the very least.
  • Martijn Pieters
    Martijn Pieters over 6 years
    @StevenRumbalski: if str.encode('rot13') ever worked in older 3.x releases then that was a mistake, as str.encode() is strict about producing bytes results only, while ROT13 is a text-to-text codec.
  • Orsiris de Jong
    Orsiris de Jong over 4 years
    Your solution is elegant, but won't handle scenarios with accents (ie éêèö and alike) because str.isalpha() returns True for those characters. Here's a lightly modified version that does not use str.isalpha(): def rot13(s): return ''.join([chr(ord(n) + (13 if 'Z' < n < 'n' or n < 'N' else -13)) if ('a' <= n <= 'z' or 'A' <= n <= 'Z') else n for n in string])
  • Boris Verkhovskiy
    Boris Verkhovskiy about 3 years
    @Ensemble the documentation says "New in version 3.2: Restoration of the rot_13 text transform." and "Changed in version 3.4: Restoration of the rot13 alias." So neither work on 3.0 and 3.1, then rot_13 works on 3.2 and 3.3 and then both rot_13 and rot13 work on 3.4+ (as well as Python 2).
  • pat
    pat almost 3 years
    Same idea with basic python: def rot13(s): m = {a:b for a,b in zip("ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")} return ''.join(m.setdefault(c, c) for c in s)
  • MadMad666
    MadMad666 over 2 years
    I liked it, very interesting way to do.