我正在尝试编写一个函数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)
'!'
我一直收到错误的输出。有人能告诉我我做错了吗?
答案 0 :(得分:2)
你的问题在这里:
new_ord = new_ord - (2*n)
这个想法是,当你超过z时,你必须完全删除整个字母,而不是删除你刚刚添加的两倍。
尝试:
new_ord = new_ord - 26
答案 1 :(得分:1)
两个班轮:(不要在家里试试)
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
答案 2 :(得分:0)
此版本还支持&#34;负旋转&#34 ;;我还将条件转换为.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
答案 3 :(得分:0)
Alternativly:
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!"