Rot13和模数的使用

时间:2014-08-09 00:16:41

标签: python string modulo rot13

我一直在读Allen B. Downey的“Think Python”,并且在其中有一个练习(8.12),作者要求创建一个ROT13函数。我做了我的,它部分起作用,因为我正在与大箱子挣扎。

以下是作者提供的解决方案的一部分:

def rotate_letter(letter, n):
"""Rotates a letter by n places.  Does not change other chars.

letter: single-letter string
n: int

Returns: single-letter string
"""
if letter.isupper():
    start = ord('A')
elif letter.islower():
    start = ord('a')
else:
    return letter

c = ord(letter) - start
i = (c + n) % 26 + start
return chr(i)

这里使用模数使得函数适用于大写字母,但我无法理解为什么! 很明显,通过使用它我们在ASCII值的开头重新开始大写,但我无法想出它背后的机制。

2 个答案:

答案 0 :(得分:2)

尝试将其分解为步骤,然后打印出中间数字。或者,更好的是,在online visualizer中运行它。

比如说,'Q'字母和数字13,你最终会得到:

'Q'.isupper() is true
start = ord('A') = 65
c = ord('Q') - start = 81 - 65 = 16
i = (c + n) % 26 + start = (16 + 13) % 26 + 65 = 29 % 26 + 65 = 3 + 65 = 68
chr(i) is 'D'

正如您所看到的,神奇的部分是(16 + 13) % 26。因此,让我们尝试在从0(对于A)到25(对于Z)的每个数字上运行它,看看会发生什么:

>>> for i in range(26):
...     print ((i + 13) % 26),
13 14 15 16 17 18 19 20 21 22 23 24 25 0 1 2 3 4 5 6 7 8 9 10 11 12

添加,然后将余数用26,意味着当你到达26时你会回到0。就像在23:00加1小时就可以让你在00:00时钟(或者,如果你&# 39;再来一个美国人,加上1小时到12点就可以到达1点。

答案 1 :(得分:2)

模26本身与大写和小写无关,需要使序列回到开头。

考虑一个简单的“腐烂1”:将字母表中的字母视为1到26之间的数字,然后加1.如果输入为'a',则取1 + 1 = 2并得到'b';如果输入为'z',则取26 + 1 = 27 - 但字母表中没有第27个字母!所以你计算27 mod 26 = 1,它“旋转”回'a'。

上面实现中大写和小写的实际技巧是start的定义,它在应用旋转之前将ASCII位置转换为数字1到26,然后使用相同的偏移量将结果返回。