0
''' 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 的单词上给了我错误的答案。我不知道为什么。请问有什么帮助吗?

4

4 回答 4

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'

您不想替换with的每个实例,只是这个。你会怎么做?好吧,如果您跟踪索引,则可以在该索引处进行替换。内置函数可让您同时获取每个索引和每个对应值。irenumerate

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,然后在最后再转换回一个字符串。)

于 2012-12-18T01:36:10.140 回答
2

我不知道 Python 喜欢在您迭代单词时如何替换单词中的字符,但似乎肯定会出现问题的一件事是重复的字母,因为replace它将替换所有出现的字母,而不仅仅是您的那个目前正在查看,因此您最终会多次移动这些重复的字母(当您在以后的迭代中再次点击它们时)。

想一想,不重复的字母也会发生这种情况。例如,在您的三个迭代中,将 ABC 移动 1 将变为 -> BBC -> CCC -> DDD。

于 2012-12-18T00:58:50.393 回答
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)
于 2012-12-18T01:48:31.963 回答
0

我也有这个任务。提示是您必须跟踪值的包装位置,并将其用于您的优势。我还建议使用upper函数调用,这样一切都是一样的,减少了检查的次数。

于 2012-12-18T01:11:26.913 回答