setcode() 的工作就是建立密碼表,我們需要的密碼表就是一個攪亂順序的英文字母表
先來溫習一下用來編碼的數學公式
y = a * x + b
m = y % n
r = m + diff
a 與 b 預定是 0 到 9 之間的隨機整數,要取得隨機整數的話,標準模組庫 (standard library) 有程式可用,倒是現在先不用急著一次到位,我們先把 a 設定成 3 , b 設定成 5 測試看看好了,如此 setcode() 的實作如下
def setcode(self): | |
# 取得 a 、 b 值 | |
a = 3 | |
b = 5 | |
# 利用公式建立密碼表 | |
self.code = "" | |
c = "a" | |
i = 0 | |
while i < 26: | |
x = c | |
y = ord(x) * a + b | |
m = y % 26 | |
self.code += chr(m + 97) | |
c = chr(ord(c) + 1) | |
i += 1 |
code 屬性 (attribute) 的初值設定為空字串 (null string)
self.code = "" |
下面設定兩個控制變數 (control variable) , c 為記錄目前處理的字母, i 則是記錄迴圈 (loop) 進行的次數
c = "a" | |
i = 0 |
因為英文字母表的小寫字母共有 26 個,因此公式用迴圈跑了 26 次
while i < 26: | |
x = c | |
y = ord(x) * a + b | |
m = y % 26 | |
self.code += chr(m + 97) | |
c = chr(ord(c) + 1) | |
i += 1 |
這裡把 c 指派給 x 後,因為 c 是字串 (string) ,使得 x 也是字串,由於字串做乘法跟加法為複製字串,所以用內建函數 (function) ord() 將 x 轉換成 Unicode 編碼值,然後才進行計算
y = ord(x) * a + b |
取得餘數 m 後,再利用內建函數 chr() 將 Unicode 編碼值轉換為單一字母的字串,這裡 += 會把單一字母的字串附加到 code 的最後
self.code += chr(m + 97) |
咦?不是說字串是不可變的 (immutable) 嗎?不可變的複合物件無法更改裡頭的元素值,那這裡為什麼可以這樣寫呢?原因很簡單,這裡是重新指派,每一次 += 都是把新的字串物件給 code ,所以沒有涉及到更改內容的問題。
最後,兩個控制變數都要遞增
c = chr(ord(c) + 1) | |
i += 1 |
我們把目前的版本放在 encrypt02.py 裡,如下
001 | # 定義 Encrypt 類別 |
002 | class Encrypt: |
003 | def __init__(self): |
004 | self.setcode() |
005 | |
006 | def setcode(self): |
007 | # 取得 a 、 b 值 |
008 | a = 3 |
009 | b = 5 |
010 | |
011 | # 利用公式建立密碼表 |
012 | self.code = "" |
013 | c = "a" |
014 | i = 0 |
015 | while i < 26: |
016 | x = c |
017 | y = ord(x) * a + b |
018 | m = y % 26 |
019 | self.code += chr(m + 97) |
020 | c = chr(ord(c) + 1) |
021 | i += 1 |
022 | |
023 | def getcode(self): |
024 | return self.code |
025 | |
026 | # 編碼的方法 |
027 | def toEncode(self, str): |
028 | pass |
029 | |
030 | # 解碼的方法 |
031 | def toDecode(self, str): |
032 | pass |
033 | |
034 | # 測試部分 |
035 | if __name__ == '__main__': |
036 | e = Encrypt() |
037 | print() |
038 | print(e.getcode()) |
039 | print() |
040 | |
041 | # 檔名: encrypt02.py |
042 | # 作者: Kaiching Chang |
043 | # 時間: July, 2014 |
測試部分就是印出密碼表,執行結果如下
結果如預期,一個英文小寫字母恰恰好對應到另外一個英文小寫字母,這樣我們的公式就 ok 了嗎? a 等於 3 跟 b 等於 5 是沒問題的,可是我們希望 a 與 b 可以是 0 到 9 之間的任意整數,這樣就有 100 種組合說,所以我們接下來要繼續測試,看看是不是每一種組合都 ok 囉!
中英文術語對照
標準模組庫 | standard library |
屬性 | attribute |
空字串 | null string |
控制變數 | control variable |
迴圈 | loop |
字串 | string |
函數 | function |
不可變的 | immutable |
重點整理
- 實作 setcode() 是先將公式中的 a 設成 3 , b 設成 5 ,然後用迴圈利用兩個控制變數 i 與 c 逐一計算每個字元。
- 內建函數 ord() 可將字串轉換成 Unicode 編碼數字,而 chr() 將 Unicode 編碼數字轉換回字串,
問題與討論
- 為什麼不把建立對換表格直接寫在 __init__() 裡就好了?
- 為什麼字串變數用 += 可以把字元附加到字串物件的最後?
練習
- 承接上一個單元的猜數字遊戲,另寫一個程式 exercise1501.py ,接受使用者輸入,加入判斷使用者是否猜對的邏輯及提示訊息。
- 承上題,另寫一個程式 exercise1502.py ,將 answer 改為字串。
the end
沒有留言:
張貼留言