Several ways to use ROT13 letter substitution cipher in Python 3

Photo by Alex Motoc on Unsplash

ROT13 (“rotate by 13 places”) is a simple letter substitution cipher, a special case of “Caesar cipher” and was once popular on Internet forums.

The rule is very simple: you replace each letters with the 13th letter behind them. If the range is over the last letter z, just loop back and continue to count from letter a. Since there are 26 letters in English, apply ROT13 twice (or 4, 6, 8 times…) will return the original text:

Although The Zen of Python said “There should be one — and preferably only one — obvious way to do it”, there are in fact many ways to implement this in Python 3. This simple article will explore some of these methods.

The straightforward way — — using ASCII index

Photo by Nick Hillier on Unsplash

The first method is to iterate the word using ord() to get the Unicode of each letter in a word (for a~z they are the same as ASCII code), calculate the new value and use chr() to convert it back to letters.

To simply things, we assume our function rot13() would only receive a single word which only consisted of a~z or A~z letters. ord(‘a’) gets 97, and chr(97) gets ‘a’. The result will be a lower case word no matter what.

The list comprehension would generates a list of converted letters, then use str.join() to combine them together into a single string without any separation characters.

So we submit a word “python” and will get the following output:

Let’s expand this a bit so it can process a longer sentence with multiple words:

If a letter does not have Unicode between 97 (‘a’) and 122 (‘z’), it would be added without changing.

This will get you

The Zen of Python way — — using dictionary

Photo by Kari Shea on Unsplash

Most Python learners probably know that you can read “The Zen of Python” by executing “import this” in REPL:

Fewer people would also know that the source code of “this” is not so straightforward — — the text is entirely coded in ROT13 and then converted back to normal English:

(So even The Zen of Python does something not beautiful, explicit and simple in Python. Funny, isn’t it?)

Let’s define a rot13() function based on the coding method above:

Here the code first builds a dictionary d as a mapping table: d[‘A’]=‘N’, d[‘B’]=‘O’, d[‘C’]=’P’, and d[‘a’]=‘n’, d[‘b’]=‘o’, etc. Then it uses list comprehension to look up letters from it. (dict.get() returns the letter itself if it is not found in the dictionary; in other words, non-alphabet characters will be unchanged.)

Using string for index and mapping instead

Photo by Maxim Fiyavchuk on Unsplash

Here’s another way to convert letters by using string as mapping table instead of a dictionary (this is based on code found here). Just the same, in order to simplify things, this rot13() would only returns lower case results.

“string.ascii_lowercase” returns a string = ‘abcde…xyz’. We use str.find() to locate the index of each letter, calculate the new positions and get the new letters. If the letter is not found in the string (get index -1, hence not an alphabet), use the original letter instead.

Using str.maketrans() and str.translate()

Photo by Edurne Chopeitia on Unsplash

There’s yet another way to make a mapping table in Python. (This is based on code found here.)

The code above is only applicable for lower case sentences. If we want to use this for both upper and lower case letters and not having to input all the alphabets twice, we can modify the code like this:

Now we have a better mapping table, and the result is

The fastest and easiest way — — using codecs

Photo by Harley-Davidson on Unsplash

For all the efforts above, the codecs module already supports ROT13 encoding, which is surprisingly simple:

Now, let’s try to use codecs.encode() on Zen of Python’s attribute s, which contains the ROT13 version of the text. Here we temporarily block/overwrite Python’s print() so module “this” won’t print the result on import, and “decode” the ROT13 string:

We will get the output

I’ll stop here and leave you to think about meanings of life, the universe and everything as well as why Python itself sometimes make things complicated.

Photo by Jared Rice on Unsplash

Former translator, after-hours Maker, sunny-day analog film shooter. Currently a junior tech-book editor based in Taiwan.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store