问题描述
嘿,我正在尝试解码多级Caesar密码。 我的意思是,一串字母可能已经移位了好几次,所以如果我说apply_shifts [(2,3),(4,5)],这意味着我将第二个字母的所有内容都移位3,然后再将第二个字母的所有内容移位。第4个字母乘5。这是到目前为止的代码。
def find_best_shifts_rec(wordlist, text, start):
"""
Given a scrambled string and a starting position from which
to decode, returns a shift key that will decode the text to
words in wordlist, or None if there is no such key.
Hint: You will find this function much easier to implement
if you use recursion.
wordlist: list of words
text: scambled 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)
"""
for shift in range(27):
text=apply_shifts(text, [(start,-shift)])
#first word is text.split()[0]
#test if first word is valid. if not, go to next shift
if is_word(wordlist,text.split()[0])==False:
continue
#enter the while loop if word is valid, otherwise never enter and go to the next shift
i=0
next_index=0
shifts={}
while is_word(wordlist,text.split()[i])==True:
next_index+= len(text.split()[i])
i=i+1
#once a word isn't valid, then try again, starting from the new index.
if is_word(wordlist,text.split()[i])==False:
shifts[next_index]=i
find_best_shifts_rec(wordlist, text, next_index)
return shifts
我的问题是
1)我的代码无法正常运行,并且我不理解为什么它搞乱了(它没有进入while循环)和2)我不知道如何测试我的“最终转移”是否没有(例如我的字符串的最后一部分)是有效的单词,我也不知道该如何再次从循环开始。
帮助将不胜感激。
1楼
我认为问题在于您总是在处理整个文本,但是在文本内部的某些开头应用(新)移位。
因此,您的检查is_word(wordlist,text.split()[0])
将始终检查第一个单词,这当然是您第一个班次后的一个单词。
您需要做的是获取新起点之后的第一个单词,因此请检查文本中实际未处理的部分。
编辑
我注意到的另一个问题是您尝试找到正确班次的方式:
for shift in range(27):
text=apply_shifts(text, [(start,-shift)])
因此,您基本上想尝试从0到26的所有移位,直到第一个单词被接受为止。
可以这样做,但是请注意,在第一次尝试移动后, 文本已更改 。
因此,您不是将其移位1, 2, 3, ...
而是将其移位1、3、6、10 1, 3, 6, 10, ...
,这当然不是您想要的,并且在执行某些操作时,您当然会错过一些移位多次相同。
因此,在继续使用文本之前,您需要暂时移动文本并检查该临时文本的状态。
或者,您总是移位1
。
编辑?
我注意到的另一个问题是您尝试使用递归来获得最终结果的方式。 通常,递归(带有结果)的工作方式与您继续调用函数本身并传递返回值或收集结果的方式相同。 在您的情况下,由于要具有多个值,而不仅仅是内部某个位置的单个值,因此需要收集每个移位结果。
但是现在,您将丢弃递归调用的返回值,而仅返回最后一个值。 因此,请存储所有值,并确保您不会丢失它们。
2楼
递归函数的伪代码:
coded_text = text from start-index to end of string
if length of coded_text is 0, return "valid solution (no shifts)"
for shift in possible_shifts:
decoded_text = apply shift of (-shift) to coded_text
first_word = split decoded_text and take first piece
if first_word is a valid word:
rest_of_solution = recurse on (text preceding start-index)+decoded_text, starting at start+(length of first_word)+1
if rest_of_solution is a valid solution
if shift is 0
return rest_of_solution
else
return (start, -shift mod alphabet_size) + rest_of_solution
# no valid solution found
return "not a valid solution"
请注意,这可以保证给出由有效词组成的答案-不一定是原始字符串。 一个特定的示例:“戴帽子”可以代替“看”来解码。