【问题标题】:Looping for every character in a string in Python decoder ring在Python解码器环中循环字符串中的每个字符
【发布时间】:2012-01-05 11:17:21
【问题描述】:

我正在尝试用 Python 制作一个简单的解码器环。

例子:

a=b, `b=c, c=d, etc.  

我希望脚本获取编码消息并输出解码消息。
例如,我会输入"ifmmp",它会输出"hello"

我一直在想我需要拆分所有字符并循环遍历它们并更改它们的 chr()ord() 值。

在 python 中似乎没有任何文档。

【问题讨论】:

  • 您认为缺少哪些文档? for 循环记录为 chr()ord()。请记住,字符串是不可变的,因此您不能只将一个字符串更改为另一个字符串,您必须使用新值创建一个新的完全字符串。此外,除非这是关于如何执行简单 for 循环的作业,否则您可能希望完全忘记循环,只需调用 string.translate()

标签: python string decoder caesar-cipher


【解决方案1】:

怎么样:

s = 'ifmmp'
new_s = ''
for c in s:
    n = ord(c)
    n = n - 1
    if n < ord('a'):
        # 'a' -> 'z'
        n = ord('z')
    new_s += chr(n)
# print('new_s = %r' % new_s)  -> new_s = 'hello'

当然,这里只处理小写字母,不处理大写。

【讨论】:

  • 抱歉,这个方案有一些不足。一个次要的问题是该函数必须为 s 中的每个字符 c 获取 ord('a'):用数字 97 替换会更好。更大的一个是new_s += chr(n) 为 s 的每个字符创建一个新字符串。如果文本是 10000 长,你会看到无用的工作......一个主要的缺陷是大写字母确实被视为所有具有 ord() ?@[]^_` 和 \t \r \n 和其他...更多在我的答案编辑中
  • @eyquem Magic numbers 绝不是我推荐的解决方案。
【解决方案2】:

忘记循环,尽可能使用 Python 内置的功能:

from string import maketrans, translate, ascii_lowercase
import functools
translation = maketrans(ascii_lowercase, ascii_lowercase[-1]+ascii_lowercase[:-1])
decipher = functools.partial(string.translate, table=translation)

print(decipher("ifmmp")) # 'hello'

【讨论】:

【解决方案3】:
from string import maketrans

table = maketrans('abcdefghijklmnopqrstuvwxyz/','zabcdefghijklmnopqrstuvwxy ')

for x in ('pdfbo','qipophsbqi','cmvf/nppo/jo/b/sfe/tlz'):
    print x,' -> ',x.translate(table)

结果

pdfbo  ->  ocean
qipophsbqi  ->  phonograph
cmvf/nppo/jo/b/sfe/tlz  ->  blue moon in a red sky

.

编辑

我重写了 Joachim 的算法(函数 better()),并编写了自己的解决方案,不使用 ma​​ketrans()yop() > ) :

s = '{ifmmp}\t\tcmvf-nppo \n SUNNY ~ ajhabh 14568'

def bof(s):
    new_s = ''
    for c in s:
        n = ord(c)
        n = n - 1
        if n < ord('a'):
            # 'a' -> 'z'
            n = ord('z')
        new_s += chr(n)
    return new_s


def better(s):
    li = []
    for c in s:
        n = ord(c)-1
        if n == 96:
            li.append('z')
        elif 96<n<122:
            li.append(chr(n))
        else:
            li.append(c)
    return ''.join(li)

def yop(s):
    gen = ((c,ord(c)-1) for c in s)
    return ''.join('z' if y==96 else chr(y) if 96<y<122 else x for x,y in gen)


def better_yop(s):
    def gen(h):
        for c in h:
            n = ord(c)-1
            if n == 96:
                yield 'z'
            elif 96<n<122:
                yield chr(n)
            else:
                yield c
    return ''.join(gen(s))

for truc in (s,bof(s),better(s),yop(s),better_yop(s)):
    print '%r\n%s\n' % (truc,truc)

结果

'{ifmmp}\t\tcmvf-nppo \n SUNNY ~ ajhabh 14568'
{ifmmp}     cmvf-nppo 
 SUNNY ~ ajhabh 14568

'zhello|zzbluezmoonzzzzzzzzz}zzigzagzzzzzz'
zhello|zzbluezmoonzzzzzzzzz}zzigzagzzzzzz

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

但是,我的函数 yop() 比函数 better()

.

编辑

现在函数 better_yop() 的速度相当于 better()
但是,better() 似乎比 better_yop() 稍快。既然也比较简单,better()是最好的

【讨论】:

    【解决方案4】:

    我建议让解码器响起字典。然后打开输入文件进行读取,读取文件,一次循环一个字符并使用字典转换为输出字符串。最后将该字符串写入文件。

    【讨论】:

    • 是的,我最终使用了 maketrans 解决方案,但是为它可能包含的所有 26 个订单制作了一个翻译表,然后让程序检查输出的英文单词,并将英文单词写入文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 2015-12-04
    • 1970-01-01
    • 2020-01-10
    相关资源
    最近更新 更多