Several ways to use ROT13 letter substitution cipher in Python 3

Image for post
Image for post
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

Image for post
Image for post
Photo by Nick Hillier on Unsplash

The first method is to iterate the word use ord() to get the Unicode of each letter in a word (which is the same as ASCII code for a~z), 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 and only consisted of a~z or A~z letters. ord(‘a’) returns 97, and chr(97) returns ‘a’. The result will be a lower case word no matter what.

The list comprehension would generates a list of converted letters, then str.join() combine them together into a single string without any separate 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

Image for post
Image for post
Photo by Kari Shea on Unsplash

Most Python learners probably know that you can read the Zen of Python by running “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 than 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 write a rot13() function based on the code above:

Here the code first builds a dictionary 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

Image for post
Image for post
Photo by Maxim Fiyavchuk on Unsplash

Here’s another way to convert letters instead of using ord()/chr() or dictionary mappings (this is based on code found here). Just the same, in order to simply things, this rot13() only returns lower case results.

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

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

Image for post
Image for post
Photo by Edurne Chopeitia on Unsplash

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

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

The result is

The fastest and easiest way — — using codecs

Image for post
Image for post
Photo by Harley-Davidson on Unsplash

For all the efforts above, the codecs module already supports ROT13 encoding, and it’s surprisingly simple:

Now lets try to use codecs.encode() on Zen of Python’s attribute s, which stores the ROT13 version of the text. Here we temporarily blocked the printing action in module “this”, 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.

Image for post
Image for post
Photo by Jared Rice on Unsplash

Written by

Former translator and currently a 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