3.5. Programming the Rail Fence Cipher#
Below is are two functions that successfully clean the text and implement the Rail Fence cipher for enciphering messages. These functions showcases many of the programming skills covered up to this point including:
functions
optional keyword arguments
loops
string slicing
conditional branches
docstrings
It does not include the code for:
deciphering 2 row rail fence messages
deciphering 3 row rail fence messages
enciphering or deciphering rail fence messages with 4 or more rows
def text_clean( text ):
"""
Arguments:
text (str): a string containing text
Returns:
(str): the input string with spaces, non letter characters removed.
letters will be upper-case
"""
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
text = text.upper()
cleaned = ''
for char in text:
if char in LETTERS:
cleaned += char
return cleaned
def railfence(text, rows, encipher=True):
"""
Example of Use:
>>> railfence('samplemessage', 3)
'SLSEAPEESGMMA'
Arguments:
text (str): represents either plaintext or ciphertext
rows (int): integer that represents the number of rows
Returns:
(str): represents the output, either plaintext or ciphertext
(str): an error message
"""
text = text_clean( text )
if rows == 2:
if encipher == True:
return text[::2].upper() + text[1::2].upper()
else:
return "this is where the 2 row decipher code will go"
elif rows == 3:
if encipher == True:
return text[::4].upper() + text[1::2].upper() + text[2::4].upper()
else:
return "this is where the 3 row decipher code will go"
else:
return "number of rails not supported"
We can see the different ways that we can use this function below:
help( railfence )
Help on function railfence in module __main__:
railfence(text, rows, encipher=True)
Example of Use:
>>> railfence('samplemessage', 3)
'SLSEAPEESGMMA'
Arguments:
text (str): represents either plaintext or ciphertext
rows (int): integer that represents the number of rows
Returns:
(str): represents the output, either plaintext or ciphertext
(str): an error message
print( railfence('samplemessage', 3) )
SLSEAPEESGMMA
print( railfence('samplemessage', 2) )
SMLMSAEAPEESG
print( railfence('samplemessage', 5) )
number of rails not supported
print( railfence('SMLMSAEAPEESG', 2, encipher=False) )
this is where the 2 row decipher code will go
print( railfence('SLSEAPEESGMMA', 3, encipher=False) )
this is where the 3 row decipher code will go
A helpful way to visualize how these two functions, text_clean
and railfence
work together, we can use the code visualization tool at Python Tutor to see the different step-by-step operations that take place. In the area below, you can resize each half of the example to see more or less of the code on the left or the diagrams on the right. Click on the next button will step through the code one line at a time. The slider allows you to move quicker through the code. The diagram on the right shows how objects are currently stored in the computer.
The functions text_clean
and railfence
are considered global
objects, meaning that every other object in the notebook as access to them at all times. You can also see that certain variables, like LETTERS
, cleaned
, and char
are local only to the text_clean
function, and other like rows
and encipher
are local only to railfence
as indicated by the box around each function in which they are contained. Other functions outside the box can’t access or alter them, unless specifically allowed access to the objects by using a return
statement.
Stepping through the code line by line allows you to see how the for
loop iterates over the LETTERS
string one character at a time, and makes a decision on whether to move it to the cleaned
string, or ignore it. Only the characters that are moved are returned back to the railfence
function, and assigned to the local variable text
.
The Python Tutor website is a great resource to see how your code is working and identify possible bugs in your code.