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'

のすべてのインスタンスを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て、最後に文字列に戻すことができます。)

于 2012-12-18T01:36:10.140 に答える
2

Python が反復処理中に単語内の文字をどのreplaceように置換するのが好きかはわかりませんが、確かに問題と思われることの 1 つは、文字の繰り返しです。現在見ているので、それらの繰り返される文字を複数回シフトすることになります(後の反復で再度ヒットするため)。

そういえば、これは繰り返しのない文字でも起こります。たとえば、ABC を 1 シフトすると、3 回の反復で -> BBC -> CCC -> DDD になります。

于 2012-12-18T00:58:50.393 に答える
0

この宿題もありました。ヒントは、値がラップする場所を追跡し、それを有利に利用する必要があるということです。また、関数呼び出しを使用することをお勧めしupperます。これにより、すべてが同じケースになり、実行するチェックの数が減ります。

于 2012-12-18T01:11:26.913 に答える
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 に答える