Cesar Cipher在Python初学者级别

时间:2012-12-18 00:54:35

标签: python python-2.7

''' 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 个答案:

答案 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)