In this exercise we will build on our Caesar Cipher from EX02 to handle uppercase and lowercase str
s of any length.
Before beginning, make sure that you have your EX02 working correctly and you have completed. Additionally, be sure you have completed Lessons 10, 11, and 12 before beginning this exercise.
Open the course workspace in VS Code (File > Open Recent > comp110-workspace) and open the File Explorer pane. Expand exercises
.
Right click on the word exercises
and select “New Folder”.
Name the folder exactly: ex03
and create a new file called cipher.py
. Copy the contents of EX02’s cipher.py
into this file as a starting point.
We want our new and improved Caesar Cipher to be able to handle both uppercase and lowercase letters. Lucky for us, python has several built-in str
methods that can help us check the case of character.
isupper
and islower
Python has a built-in str
method, isupper
, that returns True
if every alphabetic character in the str
is uppercase. Since we are only dealing with single-length str
s in encode_char
and decode_char
this method will definitively tell us if we are looking at a capitalized letter or not. You can try the following code out in a REPL
>>> "c".isupper()
False
>>> "D".isupper()
True
Unsuprisingly, there is also an islower
method that does just the opposite.
>>> "c".islower()
True
>>> "D".islower()
False
encode_char
and decode_char
With the built-ins methods shown above and our knowledge of if
statements, we have the tools under our belt to update our _char
functions to handle any character A-Z or a-z. The only difference between encoding an uppercase vs. lowercase character is the int
value used to normalize our single-length str
. In EX02, we used 97
since that is the ASCII code for a
. Now, we still want to use 97
for lowercase letters, but in the case of an uppercase character we want to use 65
. This might seem random but if we look up A
here: https://en.wikipedia.org/wiki/ASCII#Printable_characters we see that its code is 65
.
encode_char
encode_char
str
that can be assumed to be single-lengthstr
str
should be the parameter given shifted one letter to the right in the alphabet, per the mapping shown above.ord
and chr
built-in functions.decode_char
decode_char
str
that can be assumed to be single-lengthstr
str
should be the parameter given shifted one letter to the left in the alphabet, per the mapping shown above.ord
and chr
built-in functions.str
The last step is to update our encode_str
and decode_str
functions to handle str
s of any length. After this, your Caesar Cipher will be powerful enough to handle any word you give it!
To process a sequence using a loop, consider that the subscription notation expects an integer expression within the square brackets. For example, the following snippet prints every character of a str
on its own line:
letters: str = "abcdefghijklmnopqrstuvwxyz"
i: int = 0
while i < len(letters):
letter: str = letters[i]
print(letter)
i = i + 1
Notice using the len
function to determine the length of any string allows this loop to process the letters
str
no matter its contents. You will need to make use of a similar strategy for encoding and decoding a str
.
encode_str
encode_str
str
of any length.str
with the same length as the argument.str
with each letter shifted one to the right.encode_char
inside this function for each letter of the parameter.while
loop with a counter variable to complete this function. Refer to lesson 11 for information on while loops.decode_str
decode_str
str
of any length.str
with the same length as the argument.str
with each letter shifted one to the left.decode_char
inside this function for each letter of the parameter.while
loop with a counter variable to complete this function.To check that your functions work as expected, you can load your cipher
file into a REPL by opening up a new REPL
, and then running from exercises.ex03.cipher import encode_char, encode_str, decode_char, decode_str
. From here you can practice calling your functions and seeing if the results match what you expected. Once you have completed parts 1 and 2, you should be able to try combining function calls to decode and encode.
For example, decode_char
and encode_char
are inverses of each other. This means if you apply encode_char
to something followed by decode_char
, you should end up with what you started with.
decode_char(encode_char("a")) --> returns "a"
decode_char(encode_char("A")) --> returns "A"
This same property holds for decode_str
and encode_str
. You should see the following behavior:
decode_str(encode_str("flex")) --> returns "flex"
decode_str(encode_str("CaEsArCiPheR")) --> returns "CaEsArCiPheR"
For the both parts of the exercise, we will manually grade your code and are looking for good choices of meaningful variable names. Your variable names should be descriptive of their purposes. We will also manually grade to check that you declared your variables with explicit types.
Once your program is working, add a docstring at the top of your file with a one-sentence description of your program’s purpose.
Then, add your __author__
variable assigned to your name and e-mail address.
Lastly, there should be no magic numbers in your code. Make any magic numbers into named constants. Hint: due to our changes in refactoring encode_char
and decode_char
, we should have introduced another magic number into our code.