''' Cesar Cipher '''
def encrypt(word, shift):
word = word.lower()
for i in word:
r = chr(ord(i)+shift)
if r > "z":
r = chr(ord(i) - 26 + shift)
word = word.replace(i, r)
return word
if __name__ == "__main__": print encrypt("programming", 3)
这给了我错误的答案,在高于1的班次和长于2的字。我无法弄清楚为什么。有什么帮助吗?
答案 0 :(得分:4)
Thilo完全解释了这个问题。让我们一步一步:
''' Cesar Cipher '''
def encrypt(word, shift):
word = word.lower()
for i in word:
r = chr(ord(i)+shift)
if r > "z":
r = chr(ord(i) - 26 + shift)
word = word.replace(i, r)
return word
尝试encrypt('abc', 1)
,看看会发生什么:
First loop:
i = 'a'
r = chr(ord('a')+1) = 'b'
word = 'abc'.replace('a', 'b') = 'bbc'
Second loop:
i = 'b'
r = chr(ord('b')+1) = 'c'
word = 'bbc'.replace('b', 'c') = 'ccc'
Third loop:
i = 'c'
r = chr(ord('c')+1) = 'd'
word = 'ccc'.replace('c', 'd') = 'ddd'
您不希望将{em> i
的每个实例替换为r
,仅此一项。你会怎么做?好吧,如果你跟踪索引,你可以直接替换该索引。内置的enumerate
函数可以让您同时获取每个索引和每个对应的值。
for index, ch in enumerate(word):
r = chr(ord(ch)+shift)
if r > "z":
r = chr(ord(ch) - 26 + shift)
word = new_word_replacing_one_char(index, r)
现在你只需编写new_word_replacing_one_char
函数,如果你知道切片就很容易了。 (如果您尚未学习切片,可能需要将字符串转换为list
个字符,因此您只需说出word[index] = r
,然后在最后转换回字符串。)
答案 1 :(得分:2)
我不知道Python在迭代它时如何替换单词中的字符,但有一点似乎是一个问题肯定是重复的字母,因为replace
将取代所有字母的出现,而不仅仅是您当前正在查看的字母,因此您最终会多次移动这些重复的字母(当您在稍后的迭代中再次点击它们时)。
想想看,这也会发生在非重复的字母上。例如,将ABC移位1将变为 - > BBC - > CCC - >你的三次迭代中的DDD。
答案 2 :(得分:0)
我也有这个任务。提示是您必须跟踪值的包装位置,并将其用于您的优势。我还建议使用upper
函数调用,以便一切都是相同的情况,减少要执行的检查次数。
答案 3 :(得分:0)
在Python中,字符串是不可变的 - 即它们无法更改。但是,列表可以。因此,要使用您的算法,请改用列表:
''' Cesar Cipher '''
def encrypt(word, shift):
word = word.lower()
# Convert the word to a list
word = list(word)
# Iterate over the word by index
for i in xrange(len(word)):
# Get the character at i
c = word[i]
# Apply shift algorithm
r = chr(ord(c)+shift)
if r > "z":
r = chr(ord(c) - 26 + shift)
# Replace the character at i
word[i] = r
# Convert the list back to a string
return ''.join(word)
if __name__ == "__main__": print encrypt("programming", 3)