Updated for challenge 9
[cipher-tools.git] / cadenus-ciphers.ipynb
1 {
2 "metadata": {
3 "name": "",
4 "signature": "sha256:c52a83147f45ed889200fe19a5d4ec4422e884758e7d8a11536fbaafa6c627ee"
5 },
6 "nbformat": 3,
7 "nbformat_minor": 0,
8 "worksheets": [
9 {
10 "cells": [
11 {
12 "cell_type": "code",
13 "collapsed": false,
14 "input": [
15 "import matplotlib.pyplot as plt\n",
16 "import pandas as pd\n",
17 "import collections\n",
18 "import string\n",
19 "import numpy as np\n",
20 "from numpy import matrix\n",
21 "from numpy import linalg\n",
22 "%matplotlib inline\n",
23 "\n",
24 "from cipher import *\n",
25 "from cipherbreak import *\n",
26 "\n",
27 "c8a = open('2014/8a.ciphertext').read().strip()\n",
28 "c8b = open('2014/8b.ciphertext').read().strip()"
29 ],
30 "language": "python",
31 "metadata": {},
32 "outputs": [],
33 "prompt_number": 4
34 },
35 {
36 "cell_type": "code",
37 "collapsed": false,
38 "input": [
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",
43 " return letter"
44 ],
45 "language": "python",
46 "metadata": {},
47 "outputs": [],
48 "prompt_number": 2
49 },
50 {
51 "cell_type": "code",
52 "collapsed": false,
53 "input": [
54 "c8bl = ''.join([cadenus_letter(int(c, 2)) for c in chunks(c8b, 5)])\n",
55 "c8bl"
56 ],
57 "language": "python",
58 "metadata": {},
59 "outputs": [
60 {
61 "metadata": {},
62 "output_type": "pyout",
63 "prompt_number": 5,
64 "text": [
65 "'afcaeuottacthrioletcserthshtrahkzorpfrgeoadppjnglternefeofiortsddoeeumscruernfetlaafstxientrvoonerhuahravereetsvsielhlostdoalozaesmnndignnrhohhtsnaoilncnssicreanneeiiierxtanesrvogieizxssdgpvoiaisaoaeoaedrnitrnyeigrpsshadhdtoipaateyennesagrobtlesrnroirzpbgedcllixalaleenigrrnxzrlimlpstoleftrdmuarieeeiiaolnexsaohrtlstobetnslvfivdovtpoaeeisciohipseveedtexfarnhebleaotohtttepnckaonhxetmvzprreonnasgdedoeeeoaamtcicttifnadresrtserosetrhcictpsaaehldhsfysoaotctbbsoeirnsadlztrrunrceptthreuhnktaceceelrxnireeeaeseeeidisogceomnrtejhagabsenitlxtrnbmielsaretesrngsnhebiosdienafleisahocifevmfatanatrniagnhatnmibniufenrtottrnzpaidziegdnmerhhiotretcesseildrbceprigaesoadltahievebrcenlevasadnnthneiteiisahuhhuamonefzhlonxhaeeeeosneezaneisetogziterlihtcmioirarfdoetnihtnehiikamrdmnadanaodseseizclsiantaoltcizmidentthltndytttmasbleaeetlisirtxturpfailteaoefeisiiizisikvtxisprbsinelphrmohiagnlslvitodaisdpnzddcaaotahcehtueirredaectosnrhvnaodoikoetcineneurrisdcouraglvimmuppditeanditmaaiaieleonnreedaodboiumelrotntttgitnrlrienniklzsogstcifzpipvidvssmnceiasiitsnneatitomrhbnhnidprlrepoznalsnvsdosanesitfaenltgodatteeaisicrootmsmfhauenirsghznxeintegodiileedtarnosrcaaendtcuttfdrbehtmfitoordruiaozaanoeeldoinhusgiteaoriecevemntratmtfpeucutahamtnexonicdeemrpaolitoafesoosspfnlneeootachllirssysofpdftfrnpraeeazlonahautntcntcbaxloneftoatecvoxdlxvnneedtiioigtegmtaheeatefaaeprrcrosheerrpalediengidrreouhvesuroztnsosinuiuiofprda'"
66 ]
67 }
68 ],
69 "prompt_number": 5
70 },
71 {
72 "cell_type": "code",
73 "collapsed": false,
74 "input": [
75 "c8bgrid = chunks(c8bl, int(len(c8bl) / 25))\n",
76 "c8bgrid"
77 ],
78 "language": "python",
79 "metadata": {},
80 "outputs": [
81 {
82 "metadata": {},
83 "output_type": "pyout",
84 "prompt_number": 9,
85 "text": [
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']"
111 ]
112 }
113 ],
114 "prompt_number": 9
115 },
116 {
117 "cell_type": "code",
118 "collapsed": false,
119 "input": [
120 "len(c8bgrid[0])"
121 ],
122 "language": "python",
123 "metadata": {},
124 "outputs": [
125 {
126 "metadata": {},
127 "output_type": "pyout",
128 "prompt_number": 11,
129 "text": [
130 "56"
131 ]
132 }
133 ],
134 "prompt_number": 11
135 },
136 {
137 "cell_type": "code",
138 "collapsed": false,
139 "input": [
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",
143 " if reverse:\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",
149 " return keycolumn"
150 ],
151 "language": "python",
152 "metadata": {},
153 "outputs": [],
154 "prompt_number": 75
155 },
156 {
157 "cell_type": "code",
158 "collapsed": false,
159 "input": [
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",
161 "keyword = 'wink'"
162 ],
163 "language": "python",
164 "metadata": {},
165 "outputs": [],
166 "prompt_number": 36
167 },
168 {
169 "cell_type": "code",
170 "collapsed": false,
171 "input": [
172 "keycolumn = make_keycolumn(reverse=True)\n",
173 "[(k, keycolumn[k]) for k in sorted(keycolumn)]"
174 ],
175 "language": "python",
176 "metadata": {},
177 "outputs": [
178 {
179 "metadata": {},
180 "output_type": "pyout",
181 "prompt_number": 103,
182 "text": [
183 "[('a', 0),\n",
184 " ('b', 24),\n",
185 " ('c', 23),\n",
186 " ('d', 22),\n",
187 " ('e', 21),\n",
188 " ('f', 20),\n",
189 " ('g', 19),\n",
190 " ('h', 18),\n",
191 " ('i', 17),\n",
192 " ('j', 16),\n",
193 " ('k', 15),\n",
194 " ('l', 14),\n",
195 " ('m', 13),\n",
196 " ('n', 12),\n",
197 " ('o', 11),\n",
198 " ('p', 10),\n",
199 " ('q', 9),\n",
200 " ('r', 8),\n",
201 " ('s', 7),\n",
202 " ('t', 6),\n",
203 " ('u', 5),\n",
204 " ('v', 4),\n",
205 " ('w', 4),\n",
206 " ('x', 3),\n",
207 " ('y', 2),\n",
208 " ('z', 1)]"
209 ]
210 }
211 ],
212 "prompt_number": 103
213 },
214 {
215 "cell_type": "code",
216 "collapsed": false,
217 "input": [
218 "keycolumn = make_keycolumn(doubled_letters='ij', start='b', reverse=True)\n",
219 "[(k, keycolumn[k]) for k in sorted(keycolumn)]"
220 ],
221 "language": "python",
222 "metadata": {},
223 "outputs": [
224 {
225 "metadata": {},
226 "output_type": "pyout",
227 "prompt_number": 101,
228 "text": [
229 "[('a', 1),\n",
230 " ('b', 0),\n",
231 " ('c', 24),\n",
232 " ('d', 23),\n",
233 " ('e', 22),\n",
234 " ('f', 21),\n",
235 " ('g', 20),\n",
236 " ('h', 19),\n",
237 " ('i', 18),\n",
238 " ('j', 18),\n",
239 " ('k', 17),\n",
240 " ('l', 16),\n",
241 " ('m', 15),\n",
242 " ('n', 14),\n",
243 " ('o', 13),\n",
244 " ('p', 12),\n",
245 " ('q', 11),\n",
246 " ('r', 10),\n",
247 " ('s', 9),\n",
248 " ('t', 8),\n",
249 " ('u', 7),\n",
250 " ('v', 6),\n",
251 " ('w', 5),\n",
252 " ('x', 4),\n",
253 " ('y', 3),\n",
254 " ('z', 2)]"
255 ]
256 }
257 ],
258 "prompt_number": 101
259 },
260 {
261 "cell_type": "code",
262 "collapsed": false,
263 "input": [
264 "pt_rows = chunks(pt, len(pt) // 25, fillvalue='a')\n",
265 "pt_rows"
266 ],
267 "language": "python",
268 "metadata": {},
269 "outputs": [
270 {
271 "metadata": {},
272 "output_type": "pyout",
273 "prompt_number": 15,
274 "text": [
275 "['whoe',\n",
276 " 'verh',\n",
277 " 'asma',\n",
278 " 'deav',\n",
279 " 'oyag',\n",
280 " 'eupt',\n",
281 " 'hehu',\n",
282 " 'dson',\n",
283 " 'must',\n",
284 " 'reme',\n",
285 " 'mber',\n",
286 " 'thek',\n",
287 " 'aats',\n",
288 " 'kill',\n",
289 " 'moun',\n",
290 " 'tain',\n",
291 " 'sthe',\n",
292 " 'yare',\n",
293 " 'adis',\n",
294 " 'memb',\n",
295 " 'ered',\n",
296 " 'bran',\n",
297 " 'chof',\n",
298 " 'theg',\n",
299 " 'reat']"
300 ]
301 }
302 ],
303 "prompt_number": 15
304 },
305 {
306 "cell_type": "code",
307 "collapsed": false,
308 "input": [
309 "[keycolumn[l] for l in keyword]"
310 ],
311 "language": "python",
312 "metadata": {},
313 "outputs": [
314 {
315 "metadata": {},
316 "output_type": "pyout",
317 "prompt_number": 38,
318 "text": [
319 "[21, 8, 13, 10]"
320 ]
321 }
322 ],
323 "prompt_number": 38
324 },
325 {
326 "cell_type": "code",
327 "collapsed": false,
328 "input": [
329 "pt_columns = [''.join(c) for c in zip(*pt_rows)]\n",
330 "pt_columns"
331 ],
332 "language": "python",
333 "metadata": {},
334 "outputs": [
335 {
336 "metadata": {},
337 "output_type": "pyout",
338 "prompt_number": 47,
339 "text": [
340 "['wvadoehdmrmtakmtsyamebctr',\n",
341 " 'heseyuesuebhaioataderrhhe',\n",
342 " 'ormaaphosmeetluihrimeaoea',\n",
343 " 'ehavgtunterkslnneesbdnfgt']"
344 ]
345 }
346 ],
347 "prompt_number": 47
348 },
349 {
350 "cell_type": "code",
351 "collapsed": false,
352 "input": [
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)"
355 ],
356 "language": "python",
357 "metadata": {},
358 "outputs": [],
359 "prompt_number": 78
360 },
361 {
362 "cell_type": "code",
363 "collapsed": false,
364 "input": [
365 "transpositions = transpositions_of(keyword)\n",
366 "transposed = [transpose(r, transpositions) for r in rotated_pt_rows]\n",
367 "transposed"
368 ],
369 "language": "python",
370 "metadata": {},
371 "outputs": [
372 {
373 "metadata": {},
374 "output_type": "pyout",
375 "prompt_number": 79,
376 "text": [
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']]"
402 ]
403 }
404 ],
405 "prompt_number": 79
406 },
407 {
408 "cell_type": "code",
409 "collapsed": false,
410 "input": [
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))"
419 ],
420 "language": "python",
421 "metadata": {},
422 "outputs": [],
423 "prompt_number": 82
424 },
425 {
426 "cell_type": "code",
427 "collapsed": false,
428 "input": [
429 "cadenus_encipher(pt, 'wink', make_keycolumn(reverse=True))"
430 ],
431 "language": "python",
432 "metadata": {},
433 "outputs": [
434 {
435 "metadata": {},
436 "output_type": "pyout",
437 "prompt_number": 104,
438 "text": [
439 "'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned'"
440 ]
441 }
442 ],
443 "prompt_number": 104
444 },
445 {
446 "cell_type": "code",
447 "collapsed": false,
448 "input": [
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))"
452 ],
453 "language": "python",
454 "metadata": {},
455 "outputs": [
456 {
457 "metadata": {},
458 "output_type": "pyout",
459 "prompt_number": 105,
460 "text": [
461 "'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul'"
462 ]
463 }
464 ],
465 "prompt_number": 105
466 },
467 {
468 "cell_type": "code",
469 "collapsed": false,
470 "input": [
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))"
480 ],
481 "language": "python",
482 "metadata": {},
483 "outputs": [],
484 "prompt_number": 93
485 },
486 {
487 "cell_type": "code",
488 "collapsed": false,
489 "input": [
490 " cadenus_decipher('antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned',\n",
491 " 'wink',\n",
492 " make_keycolumn(reverse=True))"
493 ],
494 "language": "python",
495 "metadata": {},
496 "outputs": [
497 {
498 "metadata": {},
499 "output_type": "pyout",
500 "prompt_number": 106,
501 "text": [
502 "'whoeverhasmadeavoyageupthehudsonmustrememberthekaatskillmountainstheyareadismemberedbranchofthegreat'"
503 ]
504 }
505 ],
506 "prompt_number": 106
507 },
508 {
509 "cell_type": "code",
510 "collapsed": false,
511 "input": [
512 " cadenus_decipher('systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul',\n",
513 " 'easy',\n",
514 " make_keycolumn(reverse=True))"
515 ],
516 "language": "python",
517 "metadata": {},
518 "outputs": [
519 {
520 "metadata": {},
521 "output_type": "pyout",
522 "prompt_number": 107,
523 "text": [
524 "'aseverelimitationontheusefulnessofthecadenusisthateverymessagemustbeamultipleoftwentyfiveletterslong'"
525 ]
526 }
527 ],
528 "prompt_number": 107
529 },
530 {
531 "cell_type": "code",
532 "collapsed": false,
533 "input": [],
534 "language": "python",
535 "metadata": {},
536 "outputs": []
537 }
538 ],
539 "metadata": {}
540 }
541 ]
542 }