CS21 Lab 3: if statements, for loops

Due Saturday, March 6, before midnight (US/Eastern local to Swarthmore)

Programming Tips

As you write your first programs, start using good programming practices now:

  • Use a comment at the top of the file to describe the purpose of the program (see example).

  • All programs should have a main() function (see example).

  • Use variable names that describe the contents of the variables.

  • Write your programs incrementally and test them as you go. This is really crucial to success: don’t write lots of code and then test it all at once! Write a little code, make sure it works, then add some more and test it again.

  • Don’t assume that if your program passes the sample tests we provide that it is completely correct. Come up with your own test cases and verify that the program is producing the right output on them.

  • Avoid writing any lines of code that exceed 80 columns. In emacs, at the bottom, center of the window, there is an indication of both the line and the column of the cursor.

Are your files in the correct place?

Make sure all programs are saved to your cs21/labs/03 directory! Files outside that directory will not be graded.

$ update21
$ cd ~/cs21/labs/03
$ pwd
/home/username/cs21/labs/03
$ ls
Questions-03.txt
(should see your program files here)

Goals

The goals for this lab assignment are:

  • practice using if-else statements

  • continue working with for loops and accumulators

  • use formatted printing

1. checkpoint

At the end of your lab session, be sure to run handin21.

Your lab instructor will check your files, which should reflect that you have made non-trivial progress (in python or pseudocode) towards the solution. Note that if you have not made much progress towards your solution, we expect that you would have been actively seeking help during your lab over Slack.

10% of your lab grade is dependent on this checkpoint.

If there are circumstances which prevent you from making substantial progress on this lab, please contact your lab instructor as soon as possible.

2. Grade Calculator

Letter grades are actually a surprisingly modern development (see here or here for instance!). Let’s say that the conversion from final percentages to letter grades in a hypothetical course (that definitely isn’t CS21) were calculated as follows:

Letter Grade Percentage

A

90-100

B

80-89

C

70-79

D

60-69

NC

0-59

The starting point for this program is the determineGrade.py file that you wrote for Exercise 3C. Here you’ll write a new program called gradeCompute.py which adds a little bit more pizazz in handling user input and displaying output. Since I think emoticons are fun, your program should first ask the user if they want to see emoticons along with their final grade. If they answer yes then you should format the final output to include an emoticon that corresponds well to their final grade (perhaps an A should be paired with ʕ•́ᴥ•̀ʔっ♡ while a D should be paired with (-‸ლ)). Then the program will prompt the user for their final class average and print out their corresponding letter grade.

Some examples of running the program are shown below. You can use any emoticons you’d like, so long as there is a different one for each grade, but we’ve provided a few possible samples for reference. User input is shown in bold.

$ python3 gradeCompute.py
Would you like to see your grade in fun mode (y/n)? n
What is your final class average? 84
Your average of 84 results in a letter grade of B.

$ python3 gradeCompute.py
Would you like to see your grade in fun mode (y/n)? n
What is your final class average? 110
You can't score higher than 100! I'll treat that as 100.
Your average of 100 results in a letter grade of A.

$ python3 gradeCompute.py
Would you like to see your grade in fun mode (y/n)? n
What is your final class average? -33
You can't score less than 0! I'll treat that as 0.
Your average of 0 results in a letter grade of NC.

$ python3 gradeCompute.py
Would you like to see your grade in fun mode (y/n)? y
What is your final class average? 98
Your average of 98 results in a letter grade of A.
That's great! ʕ•́ᴥ•̀ʔっ♡

$ python3 gradeCompute.py
Would you like to see your grade in fun mode (y/n)? y
What is your final class average? 78
Your average of 78 results in a letter grade of C.
Hm... maybe you should have gone to more Ninja sessions? ( ´_ゝ`)

Your program needs to have the following features:

  • The program should use string formatting to print out the result

  • User input should be treated as integers

  • If the user enters a negative number, the program should treat that as a zero (and warn the user)

  • If the user enters a number higher than 100 the program should treat it as 100 (and warn the user)

3. Run Length Encoding

One of the ways that computers can compress files is called "run-length encoding" (although you may have seen a pretty inaccurate depiction of data compression algorithms in the show Silicon Valley). This scheme works by looking for "runs"---sequences of identical characters---and substituting the run by the character it contains, followed by the number of times that it was repeated. This method is very useful when compressing simple graphic images such as icons, line drawings, etc.

For example, consider the following string:

aaaaaaaaaabbbbbbccccc

This string has 21 characters. The character "a" appears 10 times, followed by the character "b" 6 times, then the character "c" 5 times. Using run-length encoding would give us this output string:

a10b6c5

The compressed string is only 7 characters long, compared to the original string which was 21 characters long. We can compute the "compression ratio" by dividing the number of characters in the compressed string (7) divided by the number of characters in the original string (21) to get a compression ratio of 7/21 = 0.3333333333333333, which is quite good![1]

Write a program called runLengthEncoding.py that asks the user for a string, and then displays the run-length encoded version of the string and the compression ratio (rounded to the hundredths place)

Three examples of running the program are shown below. User input is shown in bold.

$ python3 runLengthEncoding.py
string: aaaaaaaaaabbbbbbccccc
The compressed string is a10b6c5
The old string had 21 characters
The compressed string has 7 characters
Compression ratio is 0.33

$ python3 runLengthEncoding.py
string: labs
The compressed string is l1a1b1s1
The old string had 4 characters
The compressed string has 8 characters
Compression ratio is 2.0

$ python3 runLengthEncoding.py
string: aaaaabbbbbaaabcaaabbbb
The compressed string is a5b5a3b1c1a3b4
The old string had 22 characters
The compressed string has 14 characters
Compression ratio is 0.64

Some hints to get you started:

  • Your program will need one variable to keep track of the character that you are "counting". Initialize this to the first character in the string. Then make your range start from the second character of the original string.

  • Your program will also need two accumulators:

    • One to keep track of the number of times you have seen this character.

    • One for the output string.

  • You may need an extra line or two outside of your loop in order to account for and properly print the last character in the string.

4. Answer the questionnaire

Each lab will have a short questionnaire at the end. Please edit the Questions-03.txt file in your cs21/labs/03 directory and answer the questions in that file.

Once you’re done with that, run handin21 again.

5. Secret Messages — optional

This is an optional extra challenge. This part does not affect your grade so please only attempt this after completing the rest of your lab. It is simply an extra challenge, if you want to try it.

One of the most basic types of encryption is a Caesar cipher.[2] This works by replacing each letter by the letter in the alphabet that is at an index shifted by a fixed amount.

For example, consider the following string:

there is an infinite amount of hope in the universe

If we Caeser cipher encrypted that string with a shift size of 2, the resulting string would be:

vjgtg ku cp kphkpkvg coqwpv qh jqrg kp vjg wpkxgtug

That’s because the letter 't' moved 2 places further in the alphabet to 'v', 'h' gets moved to the letter 'j', etc.

Write a program called cipher.py asks the user for a shift-size and a secret message to encrypt, and it prints out the encrypted version of that message according to a Caesar cipher with the specified shift-size.

Some examples of running the program are shown below. User input is shown in bold.

$ python3 cipher.py
Please enter an (integer) encryption key: 2
Please enter your message to encrypt: hello

--------------------
Shh.... your encrypted message:  jgnnq

$ python3 cipher.py
Please enter an (integer) encryption key: 2
Please enter your message to encrypt: abcdefghijklmnopqrstuvwxyz
--------------------
Shh.... your encrypted message: cdefghijklmnopqrstuvwxyzab

$ python3 cipher.py
Please enter an (integer) encryption key: -7
Please enter your message to encrypt: Where is the Pepsi Blue!?!

--------------------
Shh.... your encrypted message:  Paxkx bl max Ixilb Uenx!?!

The last example highlights a few important points for the design of your program:

  • You need to handle both lowercase and uppercase letters. Try handling only lowercase letters first to keep things simpler. If you get that working, try adding in uppercase letters, too!

  • Any non-alphabetic characters (for instance numbers or punctuation) should pass through the cipher unchanged

  • Your program should be able to handle negative shift-sizes. In fact, using negative shifts is the simplest way to use the program for de-crypting messages!

  • To cipher the letter 'A' by 5, you can say chr(ord('A')+5) which will give you 'F'. However, you need to be careful at the boundaries of the alphabet: chr(ord('Z')+5) is the _ character and you’d like it to be 'E'. Similarly, chr(ord('A')-5) is the '<' character but you’d like it to be 'V'.

Turning in your labs…​.

Remember to run handin21 to turn in your lab files! You may run handin21 as many times as you want. Each time it will turn in any new work. We recommend running handin21 after you complete each program or after you complete significant work on any one program.


1. If we wanted to be pedantic, which is fun sometimes in computer science, we could also mention that integers usually actually take up more memory space than characters, so this scheme may actually save us slightly less memory than the reported compression ratio. Nonetheless it’s still quite good!
2. You may have also seen this implemented in an encryption scheme called ROT-13 which uses a Caesar cipher with a key of 13.