# Background Loop statements allow us to run the same block of code repeatedly, with the chance to use different values for variables each time and to produce a cumulative effect. Lists and strings are sequences that can be inspected value-by-value

CS 112 – Project 3                                                                                                                              Loops, Lists
The purpose of this assignment is to practice using loops and basic lists effectively.
Due Date: Sunday, March 3rd, 11:59pm
EC Due Date: Saturday, March 2nd, 11:59pm
For this project, you will not be charged any late tokens if you submit after the due date. However, the late submission will not be extended. The very last day you can submit is Tuesday, March 5th at 11:59pm.
See the “project basics” file for more detailed information about getting assistance, running the test file, grading, commenting, and many other extremely important things.

# Background

Loop statements allow us to run the same block of code repeatedly, with the chance to use different values for variables each time and to produce a cumulative effect. Lists and strings are sequences that can be inspected value-by-value (and modified at will). We define functions that perform calculations over sequences and numbers using loops.

Problem Statement: The internet has gone down on campus, so you can’t use your favorite messenger app to talk to people while you are in class! (like you should be chatting with friends in class in the first place…) You still want to communicate with some of your classmates across the lecture hall, but you don’t want to pass a note that the professor can plainly read and potentially embarrass you in front of the whole class. So, you have to write a program that can encrypt your messages before you send them along. This project implements a few simple ciphers (not actually secure, don’t send your bank information with these J) to encrypt your messages. You will also write a few functions to do basic frequency analysis of text.

A cipher is an algorithm used to encrypt or decrypt a message. Before a message is encrypted, it is often referred to as plaintext, and after it is encrypted it is referred to as ciphertext. In the early days of cryptography (i.e. before computers), simple substitution and transposition ciphers were used to encode sensitive messages. A substitution cipher involves a systematic replacement of each letter in the plaintext message with another letter in a predetermined scheme. Instead of replacing letters, the transposition cipher manipulates the text itself according to a defined pattern, and reads a newly formed message from this pattern. In this project, you will implement both types of ciphers.

# Restrictions

You can ask for additional functionality to be allowed, but the chances are slim that we will approve it. The general theme is, the interesting parts of the assignment must be completed by the student.

Allowed things:

• Any arithmetic/comparison/boolean operators are all fine to use, such as +, -, *, /, %, and, or, >=, < etc.
• Any control flow (selection statements, break/continue, for and while loops) can of course be used.
• The following data types: int, float, string, bool, tuple, and list. No others.
• The following sequence operations: you can index and slice sequences, you can use len() o If you need to build up a list, you can start with the empty list and .append() values into it. You can also build lists using list() and range().
• When creating lists and strings, the basic operators on them (such as +) are also allowed.
• Any functions you define on your own in your program file may be used as long as they too follow the restrictions outlined above.
• Note: standard I/O (input() and print()) are not needed since we are defining functions. You can use them for debugging purpose, but they should remove them before submission.
• Note: Not everything listed above are needed for the project.

Disallowed things:

• You may not import other modules.
• No data types not listed in the “Allowed things” section above may be used.
• No “pythonic” constructs that make certain operations trivial.
• For example, don’t use sequence[::-1] to reverse a sequence.
• No built-in functions (methods) not listed in the “Allowed things” section above may be used. For example, you may not use contains() or index().
• If you didn’t define it, you may not call it for this project!
• Missing your favorite function? Consider implementing it as a “helper function”

• You must have at least one loop in each function.
• Any incoming list parameters must not be modified in your function.
• This project has been written in a manner that does not require nested loops or multidimensional lists!

# Procedure

Create your Python file (with required comment header, see the “project basics” file) and complete the function definitions described in the next few sections. Each will need one or more loops in their solutions.

# Creating Files, Testing Your Code, and Submitting Your Project

Make sure to read the “project basics” file (“project_basics.pdf” available on Piazza under Resources). For this project you’re going to test individual functions with the tester. That information, as well as how to use the “interactive flag” for python is all described in that PDF.

Similar to Project 2, some functions will not have tests provided to you. Instead, you must test to make sure that what you have done works properly!

Correct submission:                 5 Note:  If your submission does not run (immediately
Well-documented:                   10 crashes due to errors), it will receive at most 50%. No
Code passes shared tests:          58    exceptions. As stated on our syllabus, turning in run    (zero points for hard-coding) ning code is essential. Code passes unshared tests:        27
(zero points for hard-coding)
—————————————
TOTAL:                            100
EC (submit by 3/2 at 11:59pm)      +5

# Part 1: Frequency Analysis

You must implement three functions that can compute basic things about the letters that make up a string.  Their definitions are detailed in this section.

## (6 points)

def tally(letter, text):

• Parameter(s): letter —– a string; the letter to look for                              text     —– a string; the text to look in
• Return value: An integer: the number of times that letter appeared in text Assumptions:  o text is an all lowercase string without any special characters.
• The letter is not guaranteed to appear in text.
• How it works:
• This is a reimplementation of what count() does, but with your own loop.
• Notes: o There are no provided tests for this function, you must test it on your own!
• You are not allowed to use .count()!
• Examples:
• tally(“s”,”mississippi”) 4 #  o tally(“m”,”mississippi”) 1      # o tally(“x”,”mississippi”) 0    #

## (7 points)

def frequency(text):

• Return value: A list (of integers): how often each letter of the alphabet appears in text Assumptions:
• The standard English alphabet is used: “abcdefghijklmnopqrstuvwxyz” o All strings will be entirely in lowercase, and only contain valid letters in the alphabet.
• How it works: o Count how many times each letter in the alphabet occurs in the text. ▪ Store all of these values in a list. o This list should be returned in alphabetical order:

▪ index 0 is the frequency of the letter “a”
▪ index 1 is the frequency of the letter “b”
▪ index 2 is the frequency of the letter “c” … so on until the letter “z”

• Notes: o HINT: If you haven’t written the tally() function yet…. you should do that first.
• Don’t use index() or list.count()!
• Examples:
• frequency(“abcd”) [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] o frequency(“zoosarecool”)[1,0,1,0,1,0,0,0,0,0,0,1,0,0,4,0,0,1,1,0,0,0,0,0,0,1]

## (8 points)

def common(frequencies):

• Parameter(s): frequencies — a list; the frequencies of letters in an unknown text (in alphabetical order)
• Return value: A tuple: the letter(s) that appeared most commonly in some piece of text Assumptions: o The standard English alphabet is used: “abcdefghijklmnopqrstuvwxyz”
• How it works: o This function should compute the letters in the alphabet that are “common” in a text.

▪ A “common” letter appears more than 10% of the time in a given text. o If a letter is common, add it to the tuple of common letters.

• When you have checked all of the letters in the alphabet, return the tuple of common letters. ▪ The letters should be reported in alphabetical order.
• Notes: o HINT: while the text itself is unknown, you can determine its length from the letter frequencies
• Examples:
• common([0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0]) →  (‘m’, ‘o’) o common([4,0,0,2,7,0,0,4,7,0,0,3,0,2,1,0,0,0,7,10,0,0,0,0,0,0]) →  (‘e’,’i’,’s’,’t’)

# Part 2: Substitution Ciphers

You must implement two substitution ciphers, the Atbash cipher and the Caesar cipher, where the ciphertext is created by letter substitution. The process of how letters should be substituted for one another is detailed in each function description.

## (8  points)

def atbash_cipher(plaintext):

• Parameter(s): plaintext —– a string; the message to be encrypted
• Return value: A string; the ciphertext after applying the Atbash cipher algorithm Assumptions:
• The standard English alphabet is used: “abcdefghijklmnopqrstuvwxyz” o All strings will be non-empty, entirely lowercase, and only contain valid letters in the alphabet.
• How it works:
• Flip the alphabet backwards.
• Substitute each letter in the plaintext message with its counterpart in the backwards alphabet.

▪ So, the letter “A” in the plaintext becomes “Z” in the ciphertext, the letter “B” becomes “Y,” the letter “C” becomes “X,” and so on.

• Notes: o There are no provided tests for this function, you must test it on your own!
• Remember, you cannot use .index()!
• Examples:
• atbash_cipher(“abcd”)                    ‘zyxw’ o atbash_cipher(“toocool”)            ‘gllxllo’
• atbash_cipher(“thismessagewillexplode”) ‘gsrhnvhhztvdroovckolwv’

## (8 points)

def caesar_cipher(plaintext, shift):

• Parameter(s): plaintext —– a string; the message to be encrypted shift        —– an integer; the number used to control the cipher
• Return value: A string; the ciphertext after applying the caesar cipher algorithm Assumptions:
• The standard English alphabet is used: “abcdefghijklmnopqrstuvwxyz” o All strings will be non-empty, entirely lowercase, and only contain valid letters in the alphabet. o shift will be an integer value (could be negative, positive, or zero!)
• How it works: o The substitution is performed for each character in the plaintext message based on the shift value that is provided to the function
• Each letter in the plaintext has a numbered position in the alphabet, add the shift to that position to go to a new letter in the alphabet.
• If this addition is larger than the length of the alphabet, loop around to the beginning of the alphabet. If the result of this addition is less than zero, loop around to the end of the alphabet.
• Substitute the letter in the plaintext with this new letter.
• Notes:
• Same restrictions as everything else.
• Examples:
• caesar_cipher(“quickbrownfox”, 5) ‘vznhpgwtbsktc’ o caesar_cipher(“wehavefled”, -6)  ‘qybupyzfyx’

# Part 3: Transposition Ciphers

You must implement three transposition ciphers (the “backwards” cipher, the Rail Fence cipher, and the Column Transposition cipher) where the ciphertext is created via an altered presentation of the plaintext. The algorithm for each is detailed in the function descriptions in this section.

## (13 points)

def backwards_cipher(plaintext, key):

• Parameter(s): plaintext —– a string; the message to be encrypted             key       —– an integer; the number to control this cipher
• Return value: A string; the ciphertext after applying the backwards cipher algorithm

• Assumptions:
• The standard English alphabet is used: “abcdefghijklmnopqrstuvwxyz” o All strings will be non-empty, entirely lowercase, and only contain valid letters in the alphabet.
• The key will be a positive, non-zero, number.
• How it works: o Break up the plaintext into successive subsequences of length key. Flip them all backwards, and put them back together in the same subsequence order.

For example, given the plaintext: “alexanderhamilton” and key of 4:

• Create the substrings of length 4 (if the last substring had less than 4 characters, that’s ok):

 “alex”               “ande” “rham” “ilto” “n” o Reverse each of these substrings. “xela”               “edna” “mahr” “otli” “n”

• Put them back together to get the ciphertext: “xelaednamahrotlin”

• Notes: o There are no provided tests for this function, you must test it on your own!
• It will help tremendously if you try this on paper first before you start coding.

• Examples:
• backwards_cipher(“dogsarecool”,3) ‘godrasocelo’  o backwards_cipher(“lastweekisawafilm”, 5) ‘wtsalsikeeifawaml’

## (15 points)

def fence_cipher(plaintext):

• Parameter(s): plaintext —– a string; the message to be encrypted
• Return value: A string; the ciphertext after applying the fence cipher algorithm Assumptions:
• The standard English alphabet is used: “abcdefghijklmnopqrstuvwxyz” o All strings will be non-empty, entirely lowercase, and only contain valid letters in the alphabet.
• How it works:

You “build a fence” with some number of rails (for this project we will use exactly two rails to make it simpler), and then you write letters on the rails in a zig-zag pattern. Once you’ve written all of the letters on the fence, read each rail from left to right to build the ciphertext message.

For example, given the plaintext: “vivalavieboheme”
o Build the 2-rail fence:

• Write the first letter on the top rail. Write the next letter on the bottom rail. The letter after that is written on the top rail, and so on. Repeat this pattern until you are out of letters, creating the “zig-zag” pattern seen below (spaces added for clarity, they are not required):

v . v . l . v . e . o . e . e . i . a . a . i . b . h . m .

• Read each rail from left to right:

Rail #0: “vvlveoee” Rail #1: “iaaibhm”

• Combine those strings to form the cipher text: “vvlveoeeiaaibhm”

• Notes: o This is one of the harder functions – budget your time wisely!
• It will help tremendously if you try this on paper first before you start coding

• Examples:
• fence_cipher(“meetmeinthecoverofdarkness”) ‘memiteoeodrnsetenhcvrfakes’ o   fence_cipher(“ichbineinberliner”)   ‘ihienelnrcbnibrie’

## (20 points)

def column_cipher(plaintext):

• Parameter(s): plaintext —– a string; the message to be encrypted
• Return value: A string; the ciphertext after applying the column cipher algorithm Assumptions:
• The standard English alphabet is used: “abcdefghijklmnopqrstuvwxyz” o All strings will be non-empty, entirely lowercase, and only contain valid letters in the alphabet.
• How it works: o First, transpose the text into 5 different columns by writing each letter from left to right, moving onto the next line after you exhaust all of the columns on a single line. Then, build the cipher text by combining each column from left to right.

For example, with the plaintext: “thequickbrownfoxjumped”:

• First, transpose the text into 5 different columns (spaces added for clarity, they are not required):

t h e q u i c k b r o w n f o x j u m p e d______ _

• Now, read each column one at a time:

Column #0: “tioxe”
Column #1: “hcwjd”
Column #2: “eknu”
Column #3: “qbfm”
Column #4: “urop”

• Combine the columns from left to right.
• Your final cipher text is: “tioxehcwjdeknuqbfmurop”

• Notes: o This is one of the harder functions – budget your time wisely!
• It will help tremendously if you try this on paper first before you start coding.

• Examples:
• column_cipher(“gotosecretspotatfive”) ‘gestocpftroioetvstae’ o column_cipher(“areyouhungry”) ‘aurrhyeuynog’

Posted in Uncategorized