4 "signature": "sha256:c52a83147f45ed889200fe19a5d4ec4422e884758e7d8a11536fbaafa6c627ee"
15 "import matplotlib.pyplot as plt\n",
16 "import pandas as pd\n",
17 "import collections\n",
19 "import numpy as np\n",
20 "from numpy import matrix\n",
21 "from numpy import linalg\n",
22 "%matplotlib inline\n",
24 "from cipher import *\n",
25 "from cipherbreak import *\n",
27 "c8a = open('2014/8a.ciphertext').read().strip()\n",
28 "c8b = open('2014/8b.ciphertext').read().strip()"
39 "def cadenus_letter(n, doubled='v'):\n",
40 " letter = chr(n + ord('a'))\n",
41 " if letter > doubled:\n",
42 " letter = chr(n + ord('a') + 1)\n",
54 "c8bl = ''.join([cadenus_letter(int(c, 2)) for c in chunks(c8b, 5)])\n",
62 "output_type": "pyout",
65 "'afcaeuottacthrioletcserthshtrahkzorpfrgeoadppjnglternefeofiortsddoeeumscruernfetlaafstxientrvoonerhuahravereetsvsielhlostdoalozaesmnndignnrhohhtsnaoilncnssicreanneeiiierxtanesrvogieizxssdgpvoiaisaoaeoaedrnitrnyeigrpsshadhdtoipaateyennesagrobtlesrnroirzpbgedcllixalaleenigrrnxzrlimlpstoleftrdmuarieeeiiaolnexsaohrtlstobetnslvfivdovtpoaeeisciohipseveedtexfarnhebleaotohtttepnckaonhxetmvzprreonnasgdedoeeeoaamtcicttifnadresrtserosetrhcictpsaaehldhsfysoaotctbbsoeirnsadlztrrunrceptthreuhnktaceceelrxnireeeaeseeeidisogceomnrtejhagabsenitlxtrnbmielsaretesrngsnhebiosdienafleisahocifevmfatanatrniagnhatnmibniufenrtottrnzpaidziegdnmerhhiotretcesseildrbceprigaesoadltahievebrcenlevasadnnthneiteiisahuhhuamonefzhlonxhaeeeeosneezaneisetogziterlihtcmioirarfdoetnihtnehiikamrdmnadanaodseseizclsiantaoltcizmidentthltndytttmasbleaeetlisirtxturpfailteaoefeisiiizisikvtxisprbsinelphrmohiagnlslvitodaisdpnzddcaaotahcehtueirredaectosnrhvnaodoikoetcineneurrisdcouraglvimmuppditeanditmaaiaieleonnreedaodboiumelrotntttgitnrlrienniklzsogstcifzpipvidvssmnceiasiitsnneatitomrhbnhnidprlrepoznalsnvsdosanesitfaenltgodatteeaisicrootmsmfhauenirsghznxeintegodiileedtarnosrcaaendtcuttfdrbehtmfitoordruiaozaanoeeldoinhusgiteaoriecevemntratmtfpeucutahamtnexonicdeemrpaolitoafesoosspfnlneeootachllirssysofpdftfrnpraeeazlonahautntcntcbaxloneftoatecvoxdlxvnneedtiioigtegmtaheeatefaaeprrcrosheerrpalediengidrreouhvesuroztnsosinuiuiofprda'"
75 "c8bgrid = chunks(c8bl, int(len(c8bl) / 25))\n",
83 "output_type": "pyout",
86 "['afcaeuottacthrioletcserthshtrahkzorpfrgeoadppjnglternefe',\n",
87 " 'ofiortsddoeeumscruernfetlaafstxientrvoonerhuahravereetsv',\n",
88 " 'sielhlostdoalozaesmnndignnrhohhtsnaoilncnssicreanneeiiie',\n",
89 " 'rxtanesrvogieizxssdgpvoiaisaoaeoaedrnitrnyeigrpsshadhdto',\n",
90 " 'ipaateyennesagrobtlesrnroirzpbgedcllixalaleenigrrnxzrlim',\n",
91 " 'lpstoleftrdmuarieeeiiaolnexsaohrtlstobetnslvfivdovtpoaee',\n",
92 " 'isciohipseveedtexfarnhebleaotohtttepnckaonhxetmvzprreonn',\n",
93 " 'asgdedoeeeoaamtcicttifnadresrtserosetrhcictpsaaehldhsfys',\n",
94 " 'oaotctbbsoeirnsadlztrrunrceptthreuhnktaceceelrxnireeeaes',\n",
95 " 'eeeidisogceomnrtejhagabsenitlxtrnbmielsaretesrngsnhebios',\n",
96 " 'dienafleisahocifevmfatanatrniagnhatnmibniufenrtottrnzpai',\n",
97 " 'dziegdnmerhhiotretcesseildrbceprigaesoadltahievebrcenlev',\n",
98 " 'asadnnthneiteiisahuhhuamonefzhlonxhaeeeeosneezaneisetogz',\n",
99 " 'iterlihtcmioirarfdoetnihtnehiikamrdmnadanaodseseizclsian',\n",
100 " 'taoltcizmidentthltndytttmasbleaeetlisirtxturpfailteaoefe',\n",
101 " 'isiiizisikvtxisprbsinelphrmohiagnlslvitodaisdpnzddcaaota',\n",
102 " 'hcehtueirredaectosnrhvnaodoikoetcineneurrisdcouraglvimmu',\n",
103 " 'ppditeanditmaaiaieleonnreedaodboiumelrotntttgitnrlrienni',\n",
104 " 'klzsogstcifzpipvidvssmnceiasiitsnneatitomrhbnhnidprlrepo',\n",
105 " 'znalsnvsdosanesitfaenltgodatteeaisicrootmsmfhauenirsghzn',\n",
106 " 'xeintegodiileedtarnosrcaaendtcuttfdrbehtmfitoordruiaozaa',\n",
107 " 'noeeldoinhusgiteaoriecevemntratmtfpeucutahamtnexonicdeem',\n",
108 " 'rpaolitoafesoosspfnlneeootachllirssysofpdftfrnpraeeazlon',\n",
109 " 'ahautntcntcbaxloneftoatecvoxdlxvnneedtiioigtegmtaheeatef',\n",
110 " 'aaeprrcrosheerrpalediengidrreouhvesuroztnsosinuiuiofprda']"
122 "language": "python",
127 "output_type": "pyout",
140 "def make_keycolumn(doubled_letters = 'vw', start='a', reverse=False):\n",
141 " index_to_remove = string.ascii_lowercase.find(doubled_letters[0])\n",
142 " short_alphabet = string.ascii_lowercase[:index_to_remove] + string.ascii_lowercase[index_to_remove+1:]\n",
144 " short_alphabet = ''.join(reversed(short_alphabet))\n",
145 " start_pos = short_alphabet.find(start)\n",
146 " rotated_alphabet = short_alphabet[start_pos:] + short_alphabet[:start_pos]\n",
147 " keycolumn = {l: i for i, l in enumerate(rotated_alphabet)}\n",
148 " keycolumn[doubled_letters[0]] = keycolumn[doubled_letters[1]]\n",
151 "language": "python",
160 "pt = sanitise(\"Whoever has made a voyage up the Hudson must remember the Kaatskill mountains. They are a dismembered branch of the great\")\n",
163 "language": "python",
172 "keycolumn = make_keycolumn(reverse=True)\n",
173 "[(k, keycolumn[k]) for k in sorted(keycolumn)]"
175 "language": "python",
180 "output_type": "pyout",
181 "prompt_number": 103,
218 "keycolumn = make_keycolumn(doubled_letters='ij', start='b', reverse=True)\n",
219 "[(k, keycolumn[k]) for k in sorted(keycolumn)]"
221 "language": "python",
226 "output_type": "pyout",
227 "prompt_number": 101,
264 "pt_rows = chunks(pt, len(pt) // 25, fillvalue='a')\n",
267 "language": "python",
272 "output_type": "pyout",
309 "[keycolumn[l] for l in keyword]"
311 "language": "python",
316 "output_type": "pyout",
329 "pt_columns = [''.join(c) for c in zip(*pt_rows)]\n",
332 "language": "python",
337 "output_type": "pyout",
340 "['wvadoehdmrmtakmtsyamebctr',\n",
341 " 'heseyuesuebhaioataderrhhe',\n",
342 " 'ormaaphosmeetluihrimeaoea',\n",
343 " 'ehavgtunterkslnneesbdnfgt']"
353 "rotated_pt_columns = [''.join(col[start:] + col[:start]) for start, col in zip([keycolumn[l] for l in keyword], pt_columns)] \n",
354 "rotated_pt_rows = zip(*rotated_pt_columns)"
356 "language": "python",
365 "transpositions = transpositions_of(keyword)\n",
366 "transposed = [transpose(r, transpositions) for r in rotated_pt_rows]\n",
369 "language": "python",
374 "output_type": "pyout",
377 "[['a', 'n', 't', 'o'],\n",
378 " ['d', 'e', 'l', 'e'],\n",
379 " ['e', 'e', 'u', 'h'],\n",
380 " ['r', 's', 'i', 'd'],\n",
381 " ['r', 'b', 'h', 'm'],\n",
382 " ['h', 'd', 'r', 'r'],\n",
383 " ['h', 'n', 'i', 'm'],\n",
384 " ['e', 'f', 'm', 't'],\n",
385 " ['h', 'g', 'e', 'a'],\n",
386 " ['e', 't', 'a', 'k'],\n",
387 " ['s', 'e', 'o', 'm'],\n",
388 " ['e', 'h', 'e', 't'],\n",
389 " ['y', 'a', 'a', 's'],\n",
390 " ['u', 'v', 'o', 'y'],\n",
391 " ['e', 'g', 'r', 'a'],\n",
392 " ['s', 't', 'm', 'm'],\n",
393 " ['u', 'u', 'a', 'e'],\n",
394 " ['e', 'n', 'a', 'b'],\n",
395 " ['b', 't', 'p', 'c'],\n",
396 " ['h', 'e', 'h', 't'],\n",
397 " ['a', 'r', 'o', 'r'],\n",
398 " ['i', 'k', 's', 'w'],\n",
399 " ['o', 's', 'm', 'v'],\n",
400 " ['a', 'l', 'e', 'a'],\n",
401 " ['t', 'n', 'e', 'd']]"
411 "def cadenus_encipher(message, keyword, keycolumn, fillvalue='a'):\n",
412 " rows = chunks(message, len(message) // 25, fillvalue=fillvalue)\n",
413 " columns = zip(*rows)\n",
414 " rotated_columns = [col[start:] + col[:start] for start, col in zip([keycolumn[l] for l in keyword], columns)] \n",
415 " rotated_rows = zip(*rotated_columns)\n",
416 " transpositions = transpositions_of(keyword)\n",
417 " transposed = [transpose(r, transpositions) for r in rotated_rows]\n",
418 " return ''.join(chain(*transposed))"
420 "language": "python",
429 "cadenus_encipher(pt, 'wink', make_keycolumn(reverse=True))"
431 "language": "python",
436 "output_type": "pyout",
437 "prompt_number": 104,
439 "'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned'"
449 "cadenus_encipher(sanitise('a severe limitation on the usefulness of the cadenus ' \n",
450 " 'is that every message must be a multiple of twenty-five '\n",
451 " 'letters long'), 'easy', make_keycolumn(reverse=True))"
453 "language": "python",
458 "output_type": "pyout",
459 "prompt_number": 105,
461 "'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul'"
471 "def cadenus_decipher(message, keyword, keycolumn, fillvalue='a'):\n",
472 " rows = chunks(message, len(message) // 25, fillvalue=fillvalue)\n",
473 " transpositions = transpositions_of(keyword)\n",
474 " untransposed_rows = [untranspose(r, transpositions) for r in rows]\n",
475 " columns = zip(*untransposed_rows)\n",
476 " rotated_columns = [col[-start:] + col[:-start] for start, col in zip([keycolumn[l] for l in keyword], columns)] \n",
477 " rotated_rows = zip(*rotated_columns)\n",
478 " # return rotated_columns\n",
479 " return ''.join(chain(*rotated_rows))"
481 "language": "python",
490 " cadenus_decipher('antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned',\n",
492 " make_keycolumn(reverse=True))"
494 "language": "python",
499 "output_type": "pyout",
500 "prompt_number": 106,
502 "'whoeverhasmadeavoyageupthehudsonmustrememberthekaatskillmountainstheyareadismemberedbranchofthegreat'"
512 " cadenus_decipher('systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul',\n",
514 " make_keycolumn(reverse=True))"
516 "language": "python",
521 "output_type": "pyout",
522 "prompt_number": 107,
524 "'aseverelimitationontheusefulnessofthecadenusisthateverymessagemustbeamultipleoftwentyfiveletterslong'"
534 "language": "python",