Exercises

Problem 1

Write a function named wordcount() that accepts a single string. Compute the following statistics about the string:

  1. The total number of characters.

  2. The number of words, where words are separated by whitespace (spaces, tabs, or newlines).

  3. The average word length. Punctuation counts toward the length of a word, so "Hi!" has length 3.

  4. The length of the longest word.

Return all four values, in the order listed. You may assume that the input contains at least one word.

Hint: A list comprehension may be useful.

Test Cases

print(wordcount("A B C D E F G"))
print(wordcount("A B C D\nE\tF G"))
(13, 7, 1.0, 1)
(13, 7, 1.0, 1)
print(wordcount(seuss))
print(wordcount(henryV))
(187, 40, 3.7, 9)
(2133, 408, 4.230392156862745, 13)

Problem 2

Write a function named redact() that accepts a string (the message) and a list of strings (the blacklist). For each string in the blacklist, replace every occurrence of that string in the message with asterisks, using one * for each character (for example, "eat" becomes "***"). Return the redacted message.

Test Cases

blacked = ["eat", "sleep", "study"]
print(redact("Your secret orders are to eat, read, and sleep.", blacked))
print(redact("Is it more important to study or to sleep?", blacked))
Your secret orders are to ***, read, and *****.
Is it more important to ***** or to *****?
print(redact(seuss, ["not", "green"]))
I am Sam. I am Sam. Sam I Am.
That Sam-I-am! That Sam-I-am! I do *** like that Sam-I-am!
Would you like ***** eggs and ham?
I do *** like them, Sam-I-am.
I do *** like ***** eggs and ham.
print(redact(seuss, "aeiouAEIOU"))  # Redact every vowel.
* *m S*m. * *m S*m. S*m * *m.
Th*t S*m-*-*m! Th*t S*m-*-*m! * d* n*t l*k* th*t S*m-*-*m!
W**ld y** l*k* gr**n *ggs *nd h*m?
* d* n*t l*k* th*m, S*m-*-*m.
* d* n*t l*k* gr**n *ggs *nd h*m.

Problem 3

Write a function named shift_encrypt_letter() that takes a single-character string and an integer \(n\). If the character is an uppercase letter A-Z, encrypt the letter using the Caesar cipher with key \(n\). Otherwise, return the character unchanged.

Test Cases

print(shift_encrypt_letter("A", 12))
print(shift_encrypt_letter("D", -3))
print(shift_encrypt_letter("T", 0))
print(shift_encrypt_letter("A", 7))
print(shift_encrypt_letter("!", 5))
M
A
T
H
!

Problem 4

Write a function named shift_encrypt() that accepts a string of plaintext (with one or more characters) and an integer \(n\). Encrypt the plaintext using the Caesar cipher with key \(n\). Leave characters other than A-Z unchanged.

Hint: Join the results of a list comprehension.

Test Cases

print(shift_encrypt("HELLO WORLD!", 1))
print(shift_encrypt("HELLO WORLD!", 2))
print(shift_encrypt("HELLO WORLD!", 18))
IFMMP XPSME!
JGNNQ YQTNF!
ZWDDG OGJDV!
print(shift_encrypt(seuss.upper(), 3))
L DP VDP. L DP VDP. VDP L DP.
WKDW VDP-L-DP! WKDW VDP-L-DP! L GR QRW OLNH WKDW VDP-L-DP!
ZRXOG BRX OLNH JUHHQ HJJV DQG KDP?
L GR QRW OLNH WKHP, VDP-L-DP.
L GR QRW OLNH JUHHQ HJJV DQG KDP.

Problem 5

Write a function named shift_decrypt() that accepts a string of ciphertext (with one or more characters) and an integer \(n\). Decrypt the ciphertext using the Caesar cipher with key \(n\).

Hint: Can you do this with a call to shift_encrypt() from Problem 4?

Test Cases

print(shift_decrypt("JGNNQ YQTNF!", 1))
print(shift_decrypt("JGNNQ YQTNF!", 2))
print(shift_decrypt("JGNNQ YQTNF!", 3))
IFMMP XPSME!
HELLO WORLD!
GDKKN VNQKC!

The following test checks that decryption undoes encryption for a random key \(n\).

import random

x = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG"
n = random.randint(0, 25)
print(shift_decrypt(shift_encrypt(x, n), n) == x)
True

Problem 6

When the key \(n\) used to encrypt a message is unknown, one approach to decryption is to try each of the \(26\) distinct shifts until the decrypted result looks like readable English. This so-called brute-force approach is practical for the Caesar cipher because the number of possibilities is small.

Decrypt the coded message KYV TRBV ZJ R CZV by calling shift_decrypt() with different values of the key \(n\) and reading each result. Store the value of the key \(n\) that leads to decryption in a variable named problem6_key.