疯狂挑战:Python加密函数中的旋转字母



我正在尝试编写一个函数rot(c,n),该函数将字母表中的单个字符c向前旋转n个点。

def rot(c,n):
""" rotate c forward by n characters,
    wrapping as needed; only letters change
"""
if 'a' <= c <= 'z':          # lower-case
    new_ord = ord(c) + n
    if new_ord > ord('z'):
        new_ord = new_ord - (2*n)
elif 'A' <= c <= 'Z':        # upper-case
    new_ord = ord(c) + n 
    if new_ord > ord('Z'):
        new_ord = new_ord - (2*n)
else:                        # non-alpha
    new_ord = ord(c)
return chr(new_ord)

然而,我想要的输出如下:

>>> rot('a', 2)
'c'
>>> rot('y', 2)
'a'
>>> rot('A', 3)
'D'
>>> rot('Y', 3)
'B'
>>> rot('!', 4)
'!'

我总是得到错误的输出。有人能告诉我我做错了什么吗?

您的问题在这里:

new_ord = new_ord - (2*n)

这个想法是,当你超过z时,你必须完全删除整个字母表,而不是删除刚才添加的两倍。

尝试:

new_ord = new_ord - 26

双线:(不要在家里尝试)

def rot(c, n):
    start = 97 if c.islower() else 65 if c.isupper() else False      
    return chr((ord(c)-start+n)%26 + start) if start else c

此版本还支持"负旋转";我还将条件句切换为.isupper().islower(),因为我发现它们的可读性略高(而且不太容易出现一次错误):

def rot(c,n):
    """ rotate c forward by n characters,
        wrapping as needed; only letters change
    """
    new_ord = ord(c) + (n % 26)
    if c.isupper():
        if new_ord > ord('Z'):
            new_ord -= 26
        elif new_ord < ord('A'):
            new_ord += 26
        return chr(new_ord)
    elif c.islower():
        if new_ord > ord('z'):
            new_ord -= 26
        elif new_ord < ord('a'):
            new_ord += 26
        return chr(new_ord)
    return c

可选:

import string
from itertools import cycle
def make_rotation_tables(n):    
    uc, lc = map(cycle, (string.uppercase, string.lowercase))
    nchar = len(string.uppercase)
    part = slice(n, n + nchar)
    rotate = lambda n, it: ''.join(
        [next(it) for i in xrange(26+nchar)][part])
    rot_letters = ''.join(map(lambda x: rotate(n, x), [uc, lc]))    
    return string.maketrans(string.letters, rot_letters)
rottbl = make_rotation_tables(1)
print 'Caesar dixit: "Veni, vidi, vici!"'.translate(rottbl)
>>> Dbftbs ejyju: "Wfoj, wjej, wjdj!"

最新更新