# Caesar Cipher Encrypt and decrypt homework solution.

You have to enhance the Caesar Cipher encrypt and decrypt programs, to use the words in the English Oxford Dictionary (EnglishOxfordDict.txt). First, change the decrypt program to generate the 26 Brute force (BF) output strings (distance 1 through 26). To determine which of the 26 outputs generated from the BF decrypt program is the correct output, your program should use the words from each of the 26 output strings and for each string, search for the words in the EnglishOxfordDict.txt. The string which has the most number of words that are in the words of the EnglishOxfordDict.txt is the correct English original text.

More specifically, your program should have the correct python code. Ask the user for the original input string (English sentence consisting of printable characters including printable punctuation marks).

Convert the sentence to lowercase alpha and use the Caesar cipher to encode the string using a random distance between (1 and 26). Your program should use a user-defined function to do this.

The program should print the original string, the distance used, and the encoded string.

The program should then print the 26 combinations of the decrypted string obtained by using the brute force technique of applying the distance of 1 through 26 for decrypting. The program should use a user-defined method to do this.

Read the EnglishOxfordDict.txt file and create a list of all words in the dictionary and keep them in lower case alpha. Print the total number of words in the dictionary to the screen. The program should use a user-defined function to do this.

Sequentially go through each of the words of the 26 decoded strings and check to see how many of those words for each string was found in the dictionary. Your program should use a user-defined function to do this.

Print the 26 decoded strings and for each print the number of words found in the dictionary to the screen.

Determine which string has the most number of words found in the dictionary and print that string as the FINAL string (and hopefully that is the original string).

The program should use appropriate error checking and appropriate try-except clauses to prevent the program from possible crashes due to various errors.

Submit the program as a python program.

Solution:

``` import random, re WORDS = re.compile("\w+") def caesar(text, key): encoded = [] a = ord('a') for ch in text.lower(): if ch.isalpha(): ch = chr(((ord(ch)-a + key) % 26) + a) encoded.append(ch) return "".join(encoded) def brute(text): decoded = {} for key in range(27): decoded[key] = caesar(text, 26 - key) print(f"{key}: {decoded[key]}") return decoded def OED(): words = set() try: with open("EnglishOxfordDict.txt") as f: for line in f: words.add(line.strip().lower()) print(f"Loaded {len(words)} distinct words") except: print("Problem loading dictionary") # Add the 10 most common words in English as a fallback for word in "the of and a to in is you that it".split(): words.add(word) return words def count_words(text, words): count = 0 for word in WORDS.findall(text): count += word in words return count def main(): random.seed() original = input("Enter text to encode: ") key = random.randint(1, 26) encoded = caesar(original, key) print("Original:", original) print("Distance:", key) print("Encoded:", encoded) decoded = brute(encoded) oxford = OED() counts =  for key in range(1, 27): count = count_words(decoded[key], oxford) print(f"{count} words found in", decoded[key]) counts.append(count) best = max(counts) if best: key = counts.index(best) print("Best guess:", decoded[key]) else: print("Sorry, it appears to be gibberish") if __name__ == "__main__": main() ```