【问题标题】:Python 2.7: ROT13 letter substitution cipherPython 2.7:ROT13 字母替换密码
【发布时间】:2016-05-09 12:41:00
【问题描述】:

问题陈述:

ROT13 是一种简单的字母替换密码,它用字母表中的 13 个字母替换一个字母。 ROT13 是凯撒密码的一个例子。

创建一个函数,该函数接受一个字符串并返回使用 Rot13 加密的字符串。如果字符串中包含数字或特殊字符,则应按原样返回。只有拉丁/英语字母表中的字母应该被移动,就像在原始的 Rot13“实现”中一样。

请注意,在 Python 中使用“编码”被视为作弊。

我的代码:

from string import *

def rot13(message):
    melist = list(message)

    for i in message:
        lpos = index(letters,i)

        if i.islower():
            print lpos
            melist[index(message,i)] =  lower(letters[lpos + 13])
            
        elif i.isupper():
            try:
                melist[index(message,i)] =  upper(letters[lpos + 13])
            except IndexError:
                melist[index(message,i)] =  upper(letters[lpos + 13 - 52])
                
    return ''.join(melist)

这个东西可以很好地转换除了最后一个字母之外的字符串

例如,如果你这样做:

>>> rot13('test') 
    'grft'

最后一个字符't'虽然应该改变,但我不知道我在哪里做错了。一些帮助将不胜感激。

【问题讨论】:

  • string 模块已弃用!
  • 嗯?建议使用'mystring.index(i)' 而不是import string; string.index('mystring', i)
  • @linusg 你在string 哪里看到了整个模块的弃用?
  • @DisplayName 好的,没错,不是整个 string 模块已被弃用,只有那些包含在 str 类中的函数不应再使用(如 index() 和 @ 987654331@等)

标签: python string encryption


【解决方案1】:

这里的问题不是最后一个字母。这部分代码将始终找到字符串中第一次出现的字母:

letters.index(i)

因此,即使您将'texttttttt' 作为输入,您也不会给出'test' 中最后一个't' 的索引,而是获得第一个索引 - 所有最后一个't' 将保持不变。

您必须对算法进行一些更改...

【讨论】:

  • 是的,这正是代码的问题,谢谢。
  • 您可以使用其他答案中的一个建议并接受一个!
【解决方案2】:

这是一个非常简单的 rot13 版本,它使用了 translate 函数。

import string
def rot13(message):
    norm=string.maketrans('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', \
                          'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM')
    return message.translate(norm)

print rot13("now is the time FOR ALL GOOD")

输出是
abj vf gur gvzr SBE NYY TBBQ

【讨论】:

    【解决方案3】:

    问题不在于最后一个字母,问题在于重复的字母:

    >> print rot13('abba')
    noba
    

    原因是index函数:

        index(message,i)
    

    它返回imessage第一次 出现的位置。一种解决方案是使用index() 的可选start 参数来指定搜索应从指定位置开始:

    for j,i in enumerate(message):
        lpos = index(letters,i)
    
        if i.islower():
            print lpos
    
            // this will find the correct position of the current occurence of i
            melist[index(message,i,j)] =  lower(letters[lpos + 13])
        ...
    

    【讨论】:

      【解决方案4】:

      您的问题来自使用'index'方法!

      在您的示例中,处理了第二个“t”,但结果将与列表中的第一个“t”放在同一个位置。

      我认为这里的索引没有用,你可以简单地以一个空开头,然后将每个字母附加到列表的末尾,同样:

      melist = []
      for i in message:
          if i.islower():
              melist.append(lower(letters[lpos + 13]))
      ...
      

      【讨论】: