[英]Rot13 and the use of the modulo
我一直在閱讀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值的開頭重新啟動,但是我無法弄清楚其背后的機制。
嘗試將其分解為多個步驟,然后打印出中間數字。 或者,最好在聯機可視化工具中運行它。
例如,使用字母'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時,您將回到零。就像將1小時加到23:00會使您在時鍾上達到00:00(或者,如果您是美國人,則將1小時加到12:00會使您達到1:00)。
模26本身與大寫和小寫無關,需要使序列回繞到開頭。
考慮一個簡單的“ rot 1”:將字母視為從1到26的數字,然后加1。如果輸入為'a',則取1 + 1 = 2並得到'b';如果輸入為'a',則取1 + 1 = 2。 如果輸入為“ z”,則取26 + 1 = 27-但是沒有27個字母! 因此,您計算出27 mod 26 = 1,它將“旋轉”回'a'。
在上面的實現中,大小寫的實際技巧是start
的定義,該定義在應用旋轉之前將ASCII位置轉換為數字1到26,然后使用相同的偏移量將結果返回。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.