Python微實(shí)踐 - 布萊切利莊園的秘密
? ? ? ?二戰(zhàn)時(shí)期,英國(guó)數(shù)學(xué)家、計(jì)算機(jī)科學(xué)之父Alan Turing在布萊切利莊園成功破譯了德軍密碼,為贏得世界反法西斯戰(zhàn)爭(zhēng)的勝利做出了重大貢獻(xiàn)。為了表達(dá)對(duì)前輩先賢的敬意,本微實(shí)踐取名為“布萊切利莊園的秘密”。
本文引用自作者編寫的下述圖書; 本文允許以個(gè)人學(xué)習(xí)、教學(xué)等目的引用、講授或轉(zhuǎn)載,但需要注明原作者"海洋餅干叔叔";本文不允許以紙質(zhì)及電子出版為目的進(jìn)行抄摘或改編。
1.《Python編程基礎(chǔ)及應(yīng)用》,陳波,劉慧君,高等教育出版社。免費(fèi)授課視頻
2.《Python編程基礎(chǔ)及應(yīng)用實(shí)驗(yàn)教程》, 陳波,熊心志,張全和,劉慧君,趙恒軍, 高等教育出版社
3. 《簡(jiǎn)明C及C++語(yǔ)言教程》,陳波,待出版書稿。免費(fèi)授課視頻
? ? ? ?在人類尚未獲得足夠的算力之前,加密和解密都是手工進(jìn)行的。受限于有限的人工算力,加解密只能采取一些簡(jiǎn)單的方法,比如下面這種:

? ? ? ?信息的發(fā)送方和接收方同時(shí)持有如上表所示的明密文字母對(duì)照表,該對(duì)照表對(duì)任何第三方保密。加密時(shí),按照該對(duì)照表,將明文中的a映射為f,b映射為v,…,z映射為t,即得密文。解密時(shí),同樣按照該對(duì)照表,將密文中的f映射為a,v映射為b,…,t映射為z,即得明文。
??在隨書代碼的CH6子目錄下,文件article.txt包含了示例中的“明文”,其內(nèi)容引自一本著名的英文小說(shuō):
??通過(guò)執(zhí)行CH6子目錄下的encode.py,可以將明文article.txt按前述加密方法加密成密文,文件名為encoded.txt:
? ? ? ?看起來(lái),即便密文被第三方截獲,也難以解讀,實(shí)則不然。在正常的英文表達(dá)中,每個(gè)字母出現(xiàn)的頻率是有差異的,比如e的出現(xiàn)頻次通常最高的,而z、x、q則相較較低。這提供了一種解密思路:對(duì)密文中的字母出現(xiàn)頻率進(jìn)行統(tǒng)計(jì),其中出現(xiàn)次數(shù)最高者極可能是e,次高者可能是t,最低者則可能是z、x或者q。
??應(yīng)用上述解密思路,我們?cè)O(shè)計(jì)了下述解密程序:
??第2 ~ 4行:打開當(dāng)前工作路徑下的密文文件encoded.txt,將其中的內(nèi)容按字符串形式讀出,保存在變量s中。使用Python進(jìn)行文件讀寫的詳細(xì)方法,我們?cè)诘?章中討論。 請(qǐng)讀者留意第3行中l(wèi)ower()函數(shù)的存在,在整個(gè)解密過(guò)程中,我們統(tǒng)一使用小寫字母。
??第6 ~ 9行:借助于字典stats對(duì)密文中各字母的出現(xiàn)次數(shù)進(jìn)行統(tǒng)計(jì)。統(tǒng)計(jì)完成后,stats中將得到形如{“a”:112, “x”:7, … “z”:3}的結(jié)果數(shù)據(jù)。統(tǒng)計(jì)過(guò)程中,我們使用for循環(huán)對(duì)密文s中的字符c逐一進(jìn)行處理,如果字符c是英文字母(使用成員函數(shù)isalpha()進(jìn)行判斷),則將其在字典中的出現(xiàn)次數(shù)加1。請(qǐng)讀者留意get()函數(shù)的運(yùn)用,當(dāng)某個(gè)字母是首次發(fā)現(xiàn)時(shí),其在字典中尚不存在,此時(shí),get()函數(shù)將返回默認(rèn)值0。
??第11 ~ 14行:通過(guò)列表按統(tǒng)計(jì)的頻次對(duì)字母進(jìn)行降序排序。在字典中,鍵值對(duì)之間沒有前后之分,因此排序只能通過(guò)列表進(jìn)行。第11行將字典的鍵值對(duì)轉(zhuǎn)換為列表,其內(nèi)容形式為:[(“a”,112),( “q”,3),…,(“x”,7)]。第12行使用sort()函數(shù)對(duì)該列表進(jìn)行排序,排序時(shí)通過(guò)匿名函數(shù)獲取每個(gè)元組的下標(biāo)1值,即頻次做為排序依據(jù)。第13行使用列表推導(dǎo)語(yǔ)法將有序列表中的字母單獨(dú)提取出來(lái),并使用空字符串””將所有字母串接在一起。如執(zhí)行結(jié)果的第1行所示,stats字符串的值為zufaolsjyedhpqrcvgiwnbmtkx,這表明在密文中,出現(xiàn)頻次最高的是z,然后是u,f,出現(xiàn)頻次最低是x。
??第16行:字符串codes給出了從正常語(yǔ)料庫(kù)中統(tǒng)計(jì)的字母出現(xiàn)頻次的降序排列。
??第19 ~ 24行:按照字母頻次的統(tǒng)計(jì)結(jié)果,進(jìn)行解密。字符串stats給出了密文統(tǒng)計(jì)的字母頻次降序排列,字符串codes則給出了正常語(yǔ)料統(tǒng)計(jì)的字母頻次降序排列。粗略地,我們認(rèn)為,密文字母stats[i]對(duì)應(yīng)的明文字母即為codes[i]。在下述統(tǒng)計(jì)結(jié)果中,z在密文中出現(xiàn)頻次最高,我們認(rèn)為它對(duì)應(yīng)明文字母e;u在密文中出現(xiàn)頻次為第二高,我們認(rèn)為它對(duì)應(yīng)明文字母t。
? ? ? ?解密過(guò)程中,我們使用for循環(huán)逐一處理密文s中的字符c。如果字符c是字母(isalpha()),首先通過(guò)stats.index(c)找到它在密文中的頻次排位,然后再以該頻次排位作為下標(biāo),從codes中獲得對(duì)應(yīng)的明文字母,并將明文字母附加至明文字符串r。舉例,假設(shè)c為字母”f”,stats.index(c)的結(jié)果為下標(biāo)2,對(duì)照codes[2],明文字母即為”a”。如代碼的第23 ~ 24行所示,對(duì)于那些不是字母的密文字符,直接將其附加至明文字符串r。
??第26 ~ 28行:將解密所得的明文字符串r寫入文件decoded.txt。
??使用Visual Studio Code打開解密文件decoded.txt,可見解密結(jié)果是正確的:
? ? ? ?需要說(shuō)明的是,由于密文較短,其字母頻次統(tǒng)計(jì)結(jié)果不一定能與正常語(yǔ)料統(tǒng)計(jì)的字母頻次完美對(duì)應(yīng)。此時(shí),按上述方法得到解密結(jié)果可能并不十分準(zhǔn)確,比如z被錯(cuò)誤解讀成了q。在多數(shù)字母被正確解密的情況下,少數(shù)字母的錯(cuò)誤對(duì)應(yīng)關(guān)系容易通過(guò)人工進(jìn)行校正。
? ? ? ?源程序、數(shù)據(jù)文件下載:?請(qǐng)?jiān)跒g覽器中復(fù)制并錄入下述地址
http://codelearn.club/2023/07/secretgarden/secretgarden/secretgarden.zip
為了幫助更多的年輕朋友們學(xué)好編程,作者在B站上開了兩門免費(fèi)的網(wǎng)課,一門零基礎(chǔ)講Python,一門零基礎(chǔ)C和C++一起學(xué),拿走不謝!


如果你覺得紙質(zhì)書看起來(lái)更順手,目前Python有兩本,C和C++在出版過(guò)程中。
《Python編程基礎(chǔ)及應(yīng)用》https://item.jd.com/12962124.html?

《Python編程基礎(chǔ)及應(yīng)用實(shí)驗(yàn)教程》https://item.jd.com/13218563.html

