Académique Documents
Professionnel Documents
Culture Documents
Pseudocode Solutions
Check your pseudocode against ours before you finish your implementation!
Introduction
Encryption is the process of obscuring information to make it unreadable without special
knowledge. For centuries, people have devised schemes to encrypt messages some better than
others but the advent of the computer and the Internet revolutionized the field. These days,
its hard not to encounter some sort of encryption, whether you are buying something online or
logging into Athena.
A cipher is an algorithm for performing encryption (and the reverse, decryption). The original
information is called plaintext. After it is encrypted, it is called ciphertext. The ciphertext
message contains all the information of the plaintext message, but its not in a format readable by
a human or computer without the proper mechanism to decrypt it; it should resemble random
gibberish to those not intended to read it.
A cipher usually depends on a piece of auxiliary information, called a key. The key is
incorporated into the encryption process; the same plaintext encrypted with two different keys
should have two different ciphertexts. Without the key, it should be difficult to decrypt the
resulting ciphertext into readable plaintext.
This assignment will deal with a well-known (though not very secure) encryption method called
the Caesar cipher. In this problem set you will need to devise your own algorithms and will
practice using recursion to solve a non-trivial problem.
Caesar Cipher
In this problem set, we will examine the Caesar cipher. The basic idea in this cipher is that you
pick an integer for a key, and shift every letter of your message by the key. For example, if your
message was hello and your key was 2, h becomes j, e becomes g, and so on. If youre
interested in learning more about the Caesar cipher, check out the Wikipedia article.
In this problem set, we will use a variant of the standard Caesar cipher where the space character
is included in the shifts: space is treated as the letter after z, so with a key of 2, y would
become , z would become a, and would become b.
Getting Started
Run the code without making any modifications to it, in order to ensure that everything is set up
correctly. The code that we have given you loads a list of words from a file. If everything is
okay, after a small delay, you should see the following printed out:
Loading word list from file...
55902 words loaded.
If you see an IOError instead (e.g., No such file or directory), you should change the value of the
WORDLIST_FILENAME constant (defined near the top of the file) to the complete pathname
for the file words.txt (this will vary based on where you saved the file).
The file, ps4.py, has a few functions already implemented that you can use while writing up your
solution. You can ignore the code between the following comments, though you should read and
understand everything else:
#
#
#
.
#
#
----------------------------------Helper code
(you don't need to understand this helper code)
. .
(end of helper code)
-----------------------------------
Pseudocode
Pseudocode is writing out the algorithm/solution in a form that is like code, but not quite code.
Pseudocode is language independent, uses plain English (or your native language), and is readily
understandable. Algorithm related articles in wikipedia often use pseudocode to explain the
algorithm.
Think of writing pseudocode like you would explain it to another person it doesnt generally
have to conform to any particular syntax as long as whats happening is clear to the grader.
Pseudocode is a compact and informal high-level description of a computer programming
algorithm that uses the structural conventions of a programming language, but is intended for
human reading rather than machine reading. Pseudocode typically omits details that are not
essential for human understanding of the algorithm, such as variable declarations, systemspecific code and subroutines. The purpose of using pseudocode is that it is easier for humans to
understand than conventional programming language code, and that it is a compact and
'T': 'W', 'W': 'Z', 'V': 'Y', 'Y': 'A', 'X': ' ', 'Z': 'B', 'a': 'd',
'c': 'f', 'b': 'e', 'e': 'h', 'd': 'g', 'g': 'j', 'f': 'i', 'i': 'l',
'h': 'k', 'k': 'n', 'j': 'm', 'm': 'p', 'l': 'o', 'o': 'r', 'n': 'q',
'q': 't', 'p': 's', 's': 'v', 'r': 'u', 'u': 'x', 't': 'w', 'w': 'z',
'v': 'y', 'y': 'a', 'x': ' ', 'z': 'b'}
(The order of the key-value pairs may be different.)
HINT : Use build_coder.
"""
### TODO.
def build_decoder(shift):
"""
Returns a dict that can be used to decode an encrypted text. For example,
you
could decrypt an encrypted text by calling the following commands
>>>encoder = build_encoder(shift)
>>>encrypted_text = apply_coder(plain_text, encoder)
>>>decrypted_text = apply_coder(plain_text, decoder)
The cipher is defined by the shift value. Ignores non-letter characters
like punctuation and numbers.
shift: 0 <= int < 27
returns: dict
Example:
>>> build_decoder(3)
{' ': 'x', 'A': 'Y', 'C': ' ', 'B': 'Z', 'E': 'B', 'D': 'A', 'G': 'D',
'F': 'C', 'I': 'F', 'H': 'E', 'K': 'H', 'J': 'G', 'M': 'J', 'L': 'I',
'O': 'L', 'N': 'K', 'Q': 'N', 'P': 'M', 'S': 'P', 'R': 'O', 'U': 'R',
'T': 'Q', 'W': 'T', 'V': 'S', 'Y': 'V', 'X': 'U', 'Z': 'W', 'a': 'y',
'c': ' ', 'b': 'z', 'e': 'b', 'd': 'a', 'g': 'd', 'f': 'c', 'i': 'f',
'h': 'e', 'k': 'h', 'j': 'g', 'm': 'j', 'l': 'i', 'o': 'l', 'n': 'k',
'q': 'n', 'p': 'm', 's': 'p', 'r': 'o', 'u': 'r', 't': 'q', 'w': 't',
'v': 's', 'y': 'v', 'x': 'u', 'z': 'w'}
(The order of the key-value pairs may be different.)
HINT : Use build_coder.
"""
### TODO.
def apply_coder(text, coder):
"""
Applies the coder to the text. Returns the encoded text.
text: string
coder: dict with mappings of characters to shifted characters
returns: text after mapping coder chars to original text
Example:
>>> apply_coder("Hello, world!", build_encoder(3))
'Khoor,czruog!'
>>> apply_coder("Khoor,czruog!", build_decoder(3))
'Hello, world!'
"""
### TODO.
def apply_shift(text, shift):
"""
Given a text, returns a new text Caesar shifted by the given shift
offset. The empty space counts as the 27th letter of the alphabet,
so spaces should be replaced by a lowercase letter as appropriate.
Otherwise, lower case letters should remain lower case, upper case
letters should remain upper case, and all other punctuation should
stay as it is.
text: string to apply the shift to
shift: amount to shift the text
returns: text after being shifted by specified amount.
Example:
>>> apply_shift('This is a test.', 8)
'Apq hq hiham a.'
"""
### TODO.
Once youve written this function, you should be able to use it to encode strings.
Problem 2. Code-breaking
Your friend, who is also taking 6.00, is really excited about the program she wrote for Problem 1
of this problem set. She sends you emails, but theyre all encrypted with the Caesar cipher!
The problem is, you dont know which shift key she is using. The good news is, you know your
friend only speaks and writes English words. So if you can write a program to find the decoding
that produces the maximum number of words, you can probably find the right decoding (Theres
always a chance that the shift may not be unique. Accounting for this would probably use
statistical methods that we wont require of you.)
Part a: Pseudocode
Think about an algorithm you could use to solve this problem. Write the steps down and save in
the textfile named ps4.txt.
"""
Decrypts the encoded text and returns the plaintext.
text: string
returns: 0 <= int 27
Example:
>>> s = apply_coder('Hello, world!', build_encoder(8))
>>> s
'Pmttw,hdwztl!'
>>> find_best_shift(wordlist, s) returns
8
>>> apply_coder(s, build_decoder(8)) returns
'Hello, world!'
"""
### TODO
Once youve written this function you can decode your friends emails!
Your friend has sent you another message, but this one cant be decrypted by your solution to
Problem 2 it must be using a multi-layer shift.
To keep things from getting too complicated, we will add the restriction that a shift can begin
only at the start of a word. This means that once you have found the correct shift at one location,
it is guaranteed to remain correct at least until the next occurrence of a space character.
Part a: Pseudocode
As in Problem 2, Part b, we want you to sketch out a high level step-by-step algorithm for
solving this problem. HINT: Use recursion. Save your steps in ps4.txt and upload this to your
workspace.
To solve this problem successfully, we highly recommend that you use recursion (did we say use
recursion again?). The non-recursive version of this function is much more difficult to
understand and code. The key to getting the recursion correct is in understanding the seemingly
unnecessary parameter start. As always with recursion, you should begin by thinking about
your base case, the simplest possible sub-problem you will need to solve. What value of start
would make a good base case? (Hint: the answer is NOT zero.)
To help you test your code, weve given you two simple helper functions:
random_string(wordlist, n) generates n random words from wordlist and returns them in a string.
random_scrambled(wordlist, n) generates n random words from wordlist and returns them in a
string after encrypting them with a random multi-level Caesar shift. You can start by making
sure your code decrypts a single word correctly, then move up to 2 and higher.
NOTE: This function depends on your implementation of apply_shifts, so it will not work
correctly until you have completed Problem 3.
def find_best_shifts_rec(wordlist, text, start):
"""
Given a scrambled string and a starting position from which
to decode, returns a shift key that will decode the text to
words in wordlist, or None if there is no such key.
Hint: You will find this function much easier to implement
if you use recursion.
wordlist: list of words
text: scambled text to try to find the words for
start: where to start looking at shifts
returns: list of tuples. each tuple is (position in text, amount of
shift)
"""
### TODO.
Hand-In Procedure
1. Save
You should be using ps4.txt to save your pseudocode answers. Remember, this part is turned in
after Lecture 8!
You should be using the ps4.py skeleton given to you in this problem set. Fill in the code for the
functions: build_coder(), apply_coder(), apply_shift(), find_best_shift(), apply_shifts(), and
find_best_shifts(). Any other code is not necessary. Save your solution as ps4.py. Do not ignore
this step or save your file with a different name.
MIT OpenCourseWare
http://ocw.mit.edu
For information about citing these materials or our Terms of Use, visit: http://ocw.mit.edu/terms.