0

我正在用 python 编写一个 ROT13 脚本。它通过将字符串分成单个字符列表并使用 for 循环来工作,遍历每个字母并检查它是否需要被字典翻译。

问题是它并不总是替换列表中的字母。我不知道为什么,但只有一些字符串有效。

这是代码:

import string
def rot13(m):
    Data for ROT13 conversion                                                        
    alphabet = list("abcdefghijklmnopqrstuvwxyz")
    mapping = {}
    for letter in alphabet:
        mapping[letter] = alphabet[(alphabet.index(letter) + 13)%26]
    for letter in alphabet:
        mapping[letter.upper()] = alphabet[(alphabet.index(letter) +13)%26].upper()
    # Create a list of the characters in order                                         
    characters = list(m)
    # Go through each character in the list...                                         
    for character in characters:
        # Check if that character is one that needs to be changed                      
        if character in mapping:
            # Test to chcek if it is finding characters correctly (it is)              
            print "%s to %s" % (character, mapping[character])
            # replace the character with a new one (works inconsistently)              
            characters[characters.index(character)] = mapping[character]
        #Bring it all together                                                         
        result = string.join(characters, "");
    return result

print rot13("ABCDEF") # Returns NOPQRS                                                 
print rot13("ABCDEFGHIJKLMNOPQRSTUVWXYZ") # Returns original string 

第一个测试使用部分大写字母,结果与预期一样。但是,完整的字母表在通过我的 ROT13 函数时只返回原始字符串。

我确信问题出在第 20 行,characters[characters.index(character)] = mapping[character].

这一行应该用开头构建的 rot13 字典中的对应字母替换列表中的字母,但并不总是这样做。

在打印它正在测试的字符以及根据字典应该将其更改为什么之前,我有一行,并且始终有效。但如果确实如此,那么为什么不使用另一条线呢?

4

4 回答 4

0

我使用 maketrans 表单字符串模块实现如下。

from string import maketrans
def rot_it(text):
      intab = "abcdefghijklmnopqrstuvwxyz"
      in_rot = intab + intab.upper()
      outtab = "nopqrstuvwxyzabcdefghijklm"
      out_rot = outtab + outtab.upper()
      trans = maketrans(in_rot, out_rot)
      rot13 = text.translate(trans)
      return rot13
于 2013-07-02T04:00:15.060 回答
0

试试这个版本的大小。应该更容易调试。

def translate_char(c):
    """Translate a single character using a dictionary"""
    translation_table = {
        'a':'n',
        'b':'o',
        'c':'p',
        'd':'q',
        'e':'r',
        'f':'s',
        'g':'t',
        'h':'u',
        'i':'v',
        'j':'w',
        'k':'x',
        'l':'y',
        'm':'z',
        'n':'a',
        'o':'b',
        'p':'c',
        'q':'d',
        'r':'e',
        's':'f',
        't':'g',
        'u':'h',
        'v':'i',
        'w':'j',
        'x':'k',
        'y':'l',
        'z':'m',
        'A':'N',
        'B':'O',
        'C':'P',
        'D':'Q',
        'E':'R',
        'F':'S',
        'G':'T',
        'H':'U',
        'I':'V',
        'J':'W',
        'K':'X',
        'L':'Y',
        'M':'Z',
        'N':'A',
        'O':'B',
        'P':'C',
        'Q':'D',
        'R':'E',
        'S':'F',
        'T':'G',
        'U':'H',
        'V':'I',
        'W':'J',
        'X':'K',
        'Y':'L',
        'Z':'M'}
    if c in translation_table.keys():
        return translation_table[c]
    else:
        return c    

def rot13(plaintext):
    """Translate a complete string"""
    ciphertext = ""
    for c in plaintext: 
        ciphertext = ciphertext + translate_char(c)
    return ciphertext

if __name__ == "__main__":

    plaintext = "The quick brown fox jumped over the lazy black dog."
    print rot13(plaintext)
于 2013-07-02T03:37:34.783 回答
0

索引查找列表中的第一个匹配字符。前 13 次迭代将字母表转换为 nz 重复两次。然后第二个 13 次迭代将其撤消 - 第 14 次迭代将 n 作为其字符,计算出它需要一个 a,然后调用 index ('n') 并获得 0 - 字符中第一个 'n' 的新索引。它将第一个“n”替换为“a”并继续前进。

有很多更好的方法可以编写它,但对于初学者,您应该阅读有关 enumerate 内置函数的信息。自己跟踪列表位置而不是每次都搜索至少可以解决这个问题。

于 2013-07-02T03:16:17.800 回答
0

characters.index(character)查找等于该字符的第一个元素的索引。

经过 13 次循环迭代后,您的for character in characters循环characters将看起来像这样list("NOPQRSTUVWXYZNOPQRSTUVWXYZ"),所以您最终character会得到您期望的 . 当然。"N"characters.index(character)0characters[0] = mapping["N"]characters[13] = mapping["N"]mapping["N"] == "A"

尝试:

for index, character in enumerate(characters):
    # Check if that character is one that needs to be changed                      
    if character in mapping:
        # Test to chcek if it is finding characters correctly (it is)              
        print "%s to %s" % (character, mapping[character])
        # replace the character with a new one (works inconsistently)              
        characters[index] = mapping[character]
    #Bring it all together                                                         
    result = string.join(characters, "");
于 2013-07-02T03:09:26.543 回答