I am attempting to finish a problem involving decoding a string of text encoded with multiple levels of a Caesar cipher. It seems to work for the first shift by returning Do but it will not recurse. I have print statements throughout showing the snippets I am using and putting into the functions and they seem to be correct.
def build_decoder(shift):
cipher = build_coder(shift)
decoder = {}
for k, v in cipher.items():
decoder[v] = k
return decoder
def is_word(wordlist, word):
word = word.lower()
word = word.strip(" !@#$%^&*()-_+={}[]|\:;'<>?,./\"")
return word in wordlist
def apply_coder(text, coder):
encrypted = []
for character in text:
if character in coder.keys():
encrypted.append(coder[character])
else:
encrypted.append(character)
return ''.join(encrypted)
def apply_shift(text, shift):
coder = build_coder(shift)
return apply_coder(text, coder)
def apply_shifts(text, shifts):
for index, shift in shifts:
text = (text[:index]) + (apply_coder(text[index:], build_coder(shift)))
return text
def find_best_shifts_rec(wordlist, text, start=0):
"""
text: scrambled text to try to find the words for
start: where to start looking at shifts
returns: list of tuples. each tuple is (position in text, amount of shift)
"""
key = []
for shift in range(28):
message = text[:start] + apply_shift(text[start:], -shift) #Concatenate text from beginning to start with an apply_shift from start to end of text.
space = message[start:].find(" ") #Find next space from start to " " character.
if is_word(wordlist, message[start:space]): #If text from start to space is a word.
print message[start:space]
key.append((start, shift)) #Add position and shift as tuple in list key.
print key
print len(message[:start]), message[:start]
print len(message[start:space]), message[start:space]
print len(message), message
print message[:space]
print message[space+1:]
print message[space+1]
if not(is_word(wordlist, message[start:])):
return message[:space] + find_best_shifts_rec(wordlist, message, space+1) #Return text from beginning to space(decrypted) and recursively call find_best_shifts_rec on rest of text.
else:
return message[start:]
print "No shift match found, closest match:"
print key
return ''
s = apply_shifts("Do Androids Dream of Electric Sheep?", [(0,6), (3, 18), (12, 16)])
print find_best_shifts_rec(wordlist, s)
Output:
Do
[(0, 6)]
0
2 Do
36 Do Sevif vjrKylhtgvmgLslj ypjgZollw?
Do
Sevif vjrKylhtgvmgLslj ypjgZollw?
S
No shift match found, closest match:
[]
Do