I’m a beginner when it comes to programming and Python. I’ve done most of Learn Python the Hard Way and I’m now working through Invent Your Own Computer Games with Python.
There is a chapter in the “Invent” book where you create a simple cipher program that encrypts a user submitted phrase using a key number to offset ASCII codes and using that key number to decrpyt as well. Later in the chapter, a “brute force” decryption method is added which runs through all 26 possible translations of the message and prints each of them.
I wanted to go one step further and print only the correctly translated message rather than having to look through all 26. I created a string with common words in English and tried various methods to test each generated output against that string. So far, I have been unable to find any method that works.
Here is the decryption code: (the indent blocks are correct in IDLE but not here.)
def getTranslatedMessage(mode, message, key):
if mode[0] == 'd':
key = -key
translated = ''
for symbol in message:
if symbol.isalpha():
num = ord(symbol)
num += key
if symbol.isupper():
if num > ord('Z'): num -= 26
elif num < ord('A'): num += 26
elif symbol.islower():
if num > ord('z'): num -= 26
elif num < ord('a'): num += 26
translated += chr(num)
else: translated += symbol
return translated
so when the user selects “brute force” mode, and types in a message, the following function is called:
def brute():
for key in range(1, MAX_KEY_SIZE + 1):
if words in getTranslatedMessage('decrypt', message, key).split():
print(getTranslatedMessage('decrypt', message, key))
and finally, here is the list of words I’m checking against:
words = 'and is the but or not may in it why how who where'.split()
edit:
Here is what I have now. It doesn’t work…
def brute():
for key in range(1, MAX_KEY_SIZE + 1):
if set(getTranslatedMessage('decrypt', message, key)).intersection(words_set):
print(getTranslatedMessage('decrypt', message, key))
The problem comes down to this line:
You can’t compare lists like that:
if words in somelistchecks to see whether words is an element of somelist. For example:You have some other alternatives, though.
and so on, with various levels of efficiency. Sets have very fast membership tests, so it’s generally better to use those if performance is an issue. The first any could take len(a) * len(b) steps. After fixing this (and changing brute to accept a message argument), I find your code gives:
which I think is what you wanted.