Updated for challenge 9
[cipher-tools.git] / 2017 / polybius-development.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 2,
6 "metadata": {},
7 "outputs": [],
8 "source": [
9 "import os,sys,inspect, collections\n",
10 "currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))\n",
11 "parentdir = os.path.dirname(currentdir)\n",
12 "sys.path.insert(0,parentdir) \n",
13 "\n",
14 "import matplotlib.pyplot as plt\n",
15 "%matplotlib inline\n",
16 "\n",
17 "from cipherbreak import *\n",
18 "\n",
19 "ca = open('3a.ciphertext').read()\n",
20 "cb = open('3b.ciphertext').read()"
21 ]
22 },
23 {
24 "cell_type": "code",
25 "execution_count": 6,
26 "metadata": {},
27 "outputs": [
28 {
29 "data": {
30 "text/plain": [
31 "'MHALEATASTIFETHOTSFETNRAFSSETFWTHEYAROLPOTTLEMATHPNFDAUUOOTMOTLARGSTIEETHEHODREATHEITHETINNWSRNITHETOUTAUOLOPALATBTNNVEIUNCETHEHFGERFCEIAUOLDASODVORTOGEYOUEDPBHASOICBMATHNFTTHESFWWNITNYOGIAUNLOORDHASTOLERTEDSUNFTSDEYEOTMNFLDHOVEPEERAREVATOPLEORDMATHATTHELNSSNYPIATORRAOHOVARGIEOLASEDTHOTTHEAUERAMEIEIEODARGHASUNCCFRAUOTANRSOGIAUNLOOIIORGEDTNWLORTYOLSEARYNICOTANROPNFTTHEWLORREDDASWNSATANRNYTINNWSSETTARGOTIOWARTNMHAUHTHEAUERAYELLATASSTALLFRULEOIHNMTHESOVOGETIAPESHODLEOIREDTNDEUAWHEINFIOICBSUNCCFRAUOTANRSOSTHEBHODRNMIATARGNYTHEAINMRHNMEVEIEVEIBOICBHOSATSTIOATNISORDATSEECSLAKELBTNCETHOTNRENICNIENYTHELNUOLTIAPESWENWLETFIREDSNCENRESHEODLNVENICNREBATASOLLTIEOUHEIBPFTTHASOUTTHIEOTEREDTNFRDEICARETHEECWAIESERTAIESBSTECNYSEUFIEUNCCFRAUOTANRTHEUOESOIUAWHEIWEIHOWSCNIETHORINODSHODEROPLEDTHEECWAIETNYFRUTANRSEUFIELBORDATSLNSSMOSODASOSTEITFIRARGTHOTLNSSARTNOVAUTNIBNRTHEPOTTLEYAELDDESEIVEDCNIEIEUNGRATANRTHORATIEUEAVEDWEIHOWSSFETNRAFSREVEIKREMNIWEIHOWSHEYOALEDTNFRDEISTORDTHEUFRRARGNYTHEWLORPFTEATHEIMOBDESWATETHEVAUTNIBOGIAUNLOORDTHERARTHLEGANRIECOAREDARDASGIOUENRHEOIARGTHASREMSULOFDAFSUOESOIOFGFSTFSGEICORAUFSREINECWEINIASSFEDOSEUIETWINULOCOTANRESTOPLASHARGOUAWHEISUHNNLTNDEVELNWOREMSBSTECNYACWEIAOLUAWHEISATMNIKEDARSEUIETYNINVEITMERTBBEOISDEVELNWARGREMCETHNDSTNSEUFIEUNCCFRAUOTANRSOUINSSTHEECWAIESTFDBARGTHEMNIKSNYTHEGIEEKSOGESEFULADORDHBWOTAOORDEVERNLDEIMNIKSYINCORUAERTPOPBLNRTHESUHNNLDEVELNWEDREMMOBSTNSOYEGFOIDUNCCFRAUOTANRSYINCINCESERECAESTHESEREMSBSTECSMEIEMIATTERDNMRORDDASTIAPFTEDARTHEUNDEXNUUFLTNIFCWEIHOWSTHECNSTSTIAUTLBGFOIDEDDNUFCERTAROLLHASTNIBMHERATMOSYAROLLBUNCWLETEDCORBBEOISLOTEITHEECWEINIDNCATAORASSFEDOREXEUFTAVENIDEIMHAUHWIEYOUEDEVEIBUNWBNYTHEUNDEXTHOTATMOSTNPEGFOIDEDPBEVEIBLEGANRTNTHELOSTCORTHEDEYEOTNYTHEAUERAORDTHESFAUADENYPNFDAUUOWEIHOWSWINTEUTEDTHERARTHLEGANRYINCDASSNLFTANROGIAUNLOMOSLOIGELBLEYTTNHASNMRDEVAUESARTHEWINVARUETHNFGHATMOSCODEULEOITNHACTHOTTNIETFIRMNFLDCEOROTPESTDASGIOUEORDOTMNISTDEOTHAROPIEOKMATHTIODATANRTHERARTHIOASEDOREMSTORDOIDTHELEGANRMOSEXALEDARDASGIOUETNERDFIETHEHOIDORDDORGEINFSMNIKNYSFPDFARGTHEUOLEDNRAAARTHEPLEOKMALDEIRESSESNYUOLEDNRAOSFETNRAFSNIDEIEDTHERARTHTNCOIUHTNEPNIOUFCMHAUHTHEBMEIETNCOKETHEAIPOSEYNIIOADSARTNUOLEDNRAOTHEFRSWNKERIEOSNRYNITHEAIEXALEMOSTHOTARTELLAGERUEIEWNITSSFGGESTEDTHOTTHASMOSMHEIETHEBCAGHTYARDTHEAILNSTOQFALOTHNSEMHNMNFLDIEODNRCFSTYNLLNMCBYOATHYFLSLOVETAINMHNYOUESOGIOVETOSKWEIHOWSTHELOIGESTTNDOTEOSHETIOVELSTNUNRUEOLTHEYNFITHUHOWTEINYTHASTIOGAUTOLE'"
32 ]
33 },
34 "execution_count": 6,
35 "metadata": {},
36 "output_type": "execute_result"
37 }
38 ],
39 "source": [
40 "scb = sanitise(cb)\n",
41 "scbp = chunks(scb, 2)\n",
42 "order = 'xlcdm'\n",
43 "ltrs = 'etoanisrhdlufcmwgybpvkxqz'\n",
44 "prs = [p[0] for p in collections.Counter(chunks(sanitise(cb), 2)).most_common()]\n",
45 "trans = {pr[1]: pr[0].upper() for pr in zip(ltrs, prs)}\n",
46 "scbpt = cat(trans[p] for p in scbp)\n",
47 "scbpt"
48 ]
49 },
50 {
51 "cell_type": "code",
52 "execution_count": 7,
53 "metadata": {},
54 "outputs": [
55 {
56 "data": {
57 "text/plain": [
58 "'MHALEATASTIFETHOTSFETNRAFSSETFWTHEYAROLPOTTLEMATHPNFDAUUOOTMOTLARGSTIEETHEHODREATHEITHETINNWSRNITHETOUTAUOLOPALATBTNNVEIUNCETHEHFGERFCEIAUOLDASODVORTOGEYOUEDPBHASOICBMATHNFTTHESFWWNITNYOGIAUNLOORDHASTOLERTEDSUNFTSDEYEOTMNFLDHOVEPEERAREVATOPLEORDMATHATTHELNSSNYPIATORRAOHOVARGIEOLASEDTHOTTHEAUERAMEIEIEODARGHASUNCCFRAUOTANRSOGIAUNLOOIIORGEDTNWLORTYOLSEARYNICOTANROPNFTTHEWLORREDDASWNSATANRNYTINNWSSETTARGOTIOWARTNMHAUHTHEAUERAYELLATASSTALLFRULEOIHNMTHESOVOGETIAPESHODLEOIREDTNDEUAWHEINFIOICBSUNCCFRAUOTANRSOSTHEBHODRNMIATARGNYTHEAINMRHNMEVEIEVEIBOICBHOSATSTIOATNISORDATSEECSLAKELBTNCETHOTNRENICNIENYTHELNUOLTIAPESWENWLETFIREDSNCENRESHEODLNVENICNREBATASOLLTIEOUHEIBPFTTHASOUTTHIEOTEREDTNFRDEICARETHEECWAIESERTAIESBSTECNYSEUFIEUNCCFRAUOTANRTHEUOESOIUAWHEIWEIHOWSCNIETHORINODSHODEROPLEDTHEECWAIETNYFRUTANRSEUFIELBORDATSLNSSMOSODASOSTEITFIRARGTHOTLNSSARTNOVAUTNIBNRTHEPOTTLEYAELDDESEIVEDCNIEIEUNGRATANRTHORATIEUEAVEDWEIHOWSSFETNRAFSREVEIKREMNIWEIHOWSHEYOALEDTNFRDEISTORDTHEUFRRARGNYTHEWLORPFTEATHEIMOBDESWATETHEVAUTNIBOGIAUNLOORDTHERARTHLEGANRIECOAREDARDASGIOUENRHEOIARGTHASREMSULOFDAFSUOESOIOFGFSTFSGEICORAUFSREINECWEINIASSFEDOSEUIETWINULOCOTANRESTOPLASHARGOUAWHEISUHNNLTNDEVELNWOREMSBSTECNYACWEIAOLUAWHEISATMNIKEDARSEUIETYNINVEITMERTBBEOISDEVELNWARGREMCETHNDSTNSEUFIEUNCCFRAUOTANRSOUINSSTHEECWAIESTFDBARGTHEMNIKSNYTHEGIEEKSOGESEFULADORDHBWOTAOORDEVERNLDEIMNIKSYINCORUAERTPOPBLNRTHESUHNNLDEVELNWEDREMMOBSTNSOYEGFOIDUNCCFRAUOTANRSYINCINCESERECAESTHESEREMSBSTECSMEIEMIATTERDNMRORDDASTIAPFTEDARTHEUNDEXNUUFLTNIFCWEIHOWSTHECNSTSTIAUTLBGFOIDEDDNUFCERTAROLLHASTNIBMHERATMOSYAROLLBUNCWLETEDCORBBEOISLOTEITHEECWEINIDNCATAORASSFEDOREXEUFTAVENIDEIMHAUHWIEYOUEDEVEIBUNWBNYTHEUNDEXTHOTATMOSTNPEGFOIDEDPBEVEIBLEGANRTNTHELOSTCORTHEDEYEOTNYTHEAUERAORDTHESFAUADENYPNFDAUUOWEIHOWSWINTEUTEDTHERARTHLEGANRYINCDASSNLFTANROGIAUNLOMOSLOIGELBLEYTTNHASNMRDEVAUESARTHEWINVARUETHNFGHATMOSCODEULEOITNHACTHOTTNIETFIRMNFLDCEOROTPESTDASGIOUEORDOTMNISTDEOTHAROPIEOKMATHTIODATANRTHERARTHIOASEDOREMSTORDOIDTHELEGANRMOSEXALEDARDASGIOUETNERDFIETHEHOIDORDDORGEINFSMNIKNYSFPDFARGTHEUOLEDNRAAARTHEPLEOKMALDEIRESSESNYUOLEDNRAOSFETNRAFSNIDEIEDTHERARTHTNCOIUHTNEPNIOUFCMHAUHTHEBMEIETNCOKETHEAIPOSEYNIIOADSARTNUOLEDNRAOTHEFRSWNKERIEOSNRYNITHEAIEXALEMOSTHOTARTELLAGERUEIEWNITSSFGGESTEDTHOTTHASMOSMHEIETHEBCAGHTYARDTHEAILNSTOQFALOTHNSEMHNMNFLDIEODNRCFSTYNLLNMCBYOATHYFLSLOVETAINMHNYOUESOGIOVETOSKWEIHOWSTHELOIGESTTNDOTEOSHETIOVELSTNUNRUEOLTHEYNFITHUHOWTEINYTHASTIOGAUTOLE'"
59 ]
60 },
61 "execution_count": 7,
62 "metadata": {},
63 "output_type": "execute_result"
64 }
65 ],
66 "source": [
67 "trhc = ''.maketrans('abmdefghijklcnopqrstuvwxyz', string.ascii_lowercase)\n",
68 "scbpt.translate(trhc)"
69 ]
70 },
71 {
72 "cell_type": "code",
73 "execution_count": 8,
74 "metadata": {},
75 "outputs": [],
76 "source": [
77 "def polybius_grid(keyword, column_order, row_order, letters_to_merge=None,\n",
78 " wrap_alphabet=KeywordWrapAlphabet.from_a):\n",
79 " alphabet = keyword_cipher_alphabet_of(keyword, wrap_alphabet=wrap_alphabet)\n",
80 " if letters_to_merge is None: \n",
81 " letters_to_merge = {'j': 'i'}\n",
82 " grid = {l: k \n",
83 " for k, l in zip([(c, r) for c in column_order for r in row_order],\n",
84 " [l for l in alphabet if l not in letters_to_merge])}\n",
85 " for l in letters_to_merge:\n",
86 " grid[l] = grid[letters_to_merge[l]]\n",
87 " return grid "
88 ]
89 },
90 {
91 "cell_type": "code",
92 "execution_count": 9,
93 "metadata": {},
94 "outputs": [
95 {
96 "data": {
97 "text/plain": [
98 "{'a': ('x', 'x'),\n",
99 " 'b': ('x', 'l'),\n",
100 " 'c': ('x', 'c'),\n",
101 " 'd': ('x', 'd'),\n",
102 " 'e': ('x', 'm'),\n",
103 " 'f': ('l', 'x'),\n",
104 " 'g': ('l', 'l'),\n",
105 " 'h': ('l', 'c'),\n",
106 " 'i': ('l', 'd'),\n",
107 " 'j': ('l', 'd'),\n",
108 " 'k': ('l', 'm'),\n",
109 " 'l': ('c', 'x'),\n",
110 " 'm': ('c', 'l'),\n",
111 " 'n': ('c', 'c'),\n",
112 " 'o': ('c', 'd'),\n",
113 " 'p': ('c', 'm'),\n",
114 " 'q': ('d', 'x'),\n",
115 " 'r': ('d', 'l'),\n",
116 " 's': ('d', 'c'),\n",
117 " 't': ('d', 'd'),\n",
118 " 'u': ('d', 'm'),\n",
119 " 'v': ('m', 'x'),\n",
120 " 'w': ('m', 'l'),\n",
121 " 'x': ('m', 'c'),\n",
122 " 'y': ('m', 'd'),\n",
123 " 'z': ('m', 'm')}"
124 ]
125 },
126 "execution_count": 9,
127 "metadata": {},
128 "output_type": "execute_result"
129 }
130 ],
131 "source": [
132 "polybius_grid('', order, order)"
133 ]
134 },
135 {
136 "cell_type": "code",
137 "execution_count": 10,
138 "metadata": {},
139 "outputs": [
140 {
141 "data": {
142 "text/plain": [
143 "{'a': ('a', 'a'),\n",
144 " 'b': ('a', 'b'),\n",
145 " 'c': ('a', 'c'),\n",
146 " 'd': ('a', 'd'),\n",
147 " 'e': ('a', 'e'),\n",
148 " 'f': ('b', 'a'),\n",
149 " 'g': ('b', 'b'),\n",
150 " 'h': ('b', 'c'),\n",
151 " 'i': ('b', 'd'),\n",
152 " 'j': ('b', 'd'),\n",
153 " 'k': ('b', 'e'),\n",
154 " 'l': ('c', 'a'),\n",
155 " 'm': ('c', 'b'),\n",
156 " 'n': ('c', 'c'),\n",
157 " 'o': ('c', 'd'),\n",
158 " 'p': ('c', 'e'),\n",
159 " 'q': ('d', 'a'),\n",
160 " 'r': ('d', 'b'),\n",
161 " 's': ('d', 'c'),\n",
162 " 't': ('d', 'd'),\n",
163 " 'u': ('d', 'e'),\n",
164 " 'v': ('e', 'a'),\n",
165 " 'w': ('e', 'b'),\n",
166 " 'x': ('e', 'c'),\n",
167 " 'y': ('e', 'd'),\n",
168 " 'z': ('e', 'e')}"
169 ]
170 },
171 "execution_count": 10,
172 "metadata": {},
173 "output_type": "execute_result"
174 }
175 ],
176 "source": [
177 "polybius_grid('a', 'abcde', 'abcde')"
178 ]
179 },
180 {
181 "cell_type": "code",
182 "execution_count": 11,
183 "metadata": {},
184 "outputs": [
185 {
186 "data": {
187 "text/plain": [
188 "True"
189 ]
190 },
191 "execution_count": 11,
192 "metadata": {},
193 "output_type": "execute_result"
194 }
195 ],
196 "source": [
197 "polybius_grid('elephant', 'abcde', 'abcde')['b'] == ('b', 'c')"
198 ]
199 },
200 {
201 "cell_type": "code",
202 "execution_count": 12,
203 "metadata": {},
204 "outputs": [
205 {
206 "data": {
207 "text/plain": [
208 "True"
209 ]
210 },
211 "execution_count": 12,
212 "metadata": {},
213 "output_type": "execute_result"
214 }
215 ],
216 "source": [
217 "polybius_grid('elephant', 'abcde', 'abcde')['e'] == ('a', 'a')"
218 ]
219 },
220 {
221 "cell_type": "code",
222 "execution_count": 13,
223 "metadata": {},
224 "outputs": [],
225 "source": [
226 "def polybius_reverse_grid(keyword, column_order, row_order, letters_to_merge=None,\n",
227 " wrap_alphabet=KeywordWrapAlphabet.from_a):\n",
228 " alphabet = keyword_cipher_alphabet_of(keyword, wrap_alphabet=wrap_alphabet)\n",
229 " if letters_to_merge is None: \n",
230 " letters_to_merge = {'j': 'i'}\n",
231 " grid = {k: l \n",
232 " for k, l in zip([(c, r) for c in column_order for r in row_order],\n",
233 " [l for l in alphabet if l not in letters_to_merge])}\n",
234 "# for l in letters_to_merge:\n",
235 "# for r, c in grid:\n",
236 "# if grid[r, c] == letters_to_merge[l]:\n",
237 "# grid[l] = grid[r, c]\n",
238 " return grid "
239 ]
240 },
241 {
242 "cell_type": "code",
243 "execution_count": 14,
244 "metadata": {},
245 "outputs": [
246 {
247 "data": {
248 "text/plain": [
249 "{('c', 'c'): 'n',\n",
250 " ('c', 'd'): 'o',\n",
251 " ('c', 'l'): 'm',\n",
252 " ('c', 'm'): 'p',\n",
253 " ('c', 'x'): 'l',\n",
254 " ('d', 'c'): 's',\n",
255 " ('d', 'd'): 't',\n",
256 " ('d', 'l'): 'r',\n",
257 " ('d', 'm'): 'u',\n",
258 " ('d', 'x'): 'q',\n",
259 " ('l', 'c'): 'h',\n",
260 " ('l', 'd'): 'i',\n",
261 " ('l', 'l'): 'g',\n",
262 " ('l', 'm'): 'k',\n",
263 " ('l', 'x'): 'f',\n",
264 " ('m', 'c'): 'x',\n",
265 " ('m', 'd'): 'y',\n",
266 " ('m', 'l'): 'w',\n",
267 " ('m', 'm'): 'z',\n",
268 " ('m', 'x'): 'v',\n",
269 " ('x', 'c'): 'c',\n",
270 " ('x', 'd'): 'd',\n",
271 " ('x', 'l'): 'b',\n",
272 " ('x', 'm'): 'e',\n",
273 " ('x', 'x'): 'a'}"
274 ]
275 },
276 "execution_count": 14,
277 "metadata": {},
278 "output_type": "execute_result"
279 }
280 ],
281 "source": [
282 "polybius_reverse_grid('', order, order)"
283 ]
284 },
285 {
286 "cell_type": "code",
287 "execution_count": 15,
288 "metadata": {},
289 "outputs": [],
290 "source": [
291 "def polybius_flatten(pair, column_first):\n",
292 " if column_first:\n",
293 " return str(pair[1]) + str(pair[0])\n",
294 " else:\n",
295 " return str(pair[0]) + str(pair[1])"
296 ]
297 },
298 {
299 "cell_type": "code",
300 "execution_count": 16,
301 "metadata": {},
302 "outputs": [],
303 "source": [
304 "def polybius_encipher(message, keyword, column_order, row_order, \n",
305 " column_first=False,\n",
306 " letters_to_merge=None, wrap_alphabet=KeywordWrapAlphabet.from_a): \n",
307 " grid = polybius_grid(keyword, column_order, row_order, letters_to_merge, wrap_alphabet)\n",
308 " return cat(polybius_flatten(grid[l], column_first)\n",
309 " for l in message\n",
310 " if l in grid)"
311 ]
312 },
313 {
314 "cell_type": "code",
315 "execution_count": 17,
316 "metadata": {},
317 "outputs": [
318 {
319 "data": {
320 "text/plain": [
321 "'mllcldcxxmldddlddcdddldmxm'"
322 ]
323 },
324 "execution_count": 17,
325 "metadata": {},
326 "output_type": "execute_result"
327 }
328 ],
329 "source": [
330 "polybius_encipher('while it is true', '', order, order)"
331 ]
332 },
333 {
334 "cell_type": "code",
335 "execution_count": 18,
336 "metadata": {},
337 "outputs": [
338 {
339 "data": {
340 "text/plain": [
341 "'mllcldcxxmldddlddcdddldmxmddlcxxdddcdmxmddcdcclddmdcdcxmdddmcmddlcxmlxldccxxcxxlxxdd'"
342 ]
343 },
344 "execution_count": 18,
345 "metadata": {},
346 "output_type": "execute_result"
347 }
348 ],
349 "source": [
350 "sanitise(cb[:100])"
351 ]
352 },
353 {
354 "cell_type": "code",
355 "execution_count": 19,
356 "metadata": {},
357 "outputs": [],
358 "source": [
359 "def polybius_decipher(message, keyword, column_order, row_order, \n",
360 " column_first=False,\n",
361 " letters_to_merge=None, wrap_alphabet=KeywordWrapAlphabet.from_a): \n",
362 " grid = polybius_reverse_grid(keyword, column_order, row_order, letters_to_merge, wrap_alphabet)\n",
363 " column_index_type = type(column_order[0])\n",
364 " row_index_type = type(row_order[0])\n",
365 " if column_first:\n",
366 " pairs = [(column_index_type(p[1]), row_index_type(p[0])) for p in chunks(message, 2)]\n",
367 " else:\n",
368 " pairs = [(row_index_type(p[0]), column_index_type(p[1])) for p in chunks(message, 2)]\n",
369 " return cat(grid[p] for p in pairs if p in grid)"
370 ]
371 },
372 {
373 "cell_type": "code",
374 "execution_count": 20,
375 "metadata": {},
376 "outputs": [
377 {
378 "data": {
379 "text/plain": [
380 "'whileitistrue'"
381 ]
382 },
383 "execution_count": 20,
384 "metadata": {},
385 "output_type": "execute_result"
386 }
387 ],
388 "source": [
389 "polybius_decipher('mllcldcxxmldddlddcdddldmxm', '', order, order)"
390 ]
391 },
392 {
393 "cell_type": "code",
394 "execution_count": 21,
395 "metadata": {},
396 "outputs": [
397 {
398 "data": {
399 "text/plain": [
400 "'lmcldlxcmxdldddlcdddldmdmx'"
401 ]
402 },
403 "execution_count": 21,
404 "metadata": {},
405 "output_type": "execute_result"
406 }
407 ],
408 "source": [
409 "polybius_encipher('whileitistrue', '', order, order, column_first=True)"
410 ]
411 },
412 {
413 "cell_type": "code",
414 "execution_count": 22,
415 "metadata": {},
416 "outputs": [
417 {
418 "data": {
419 "text/plain": [
420 "'kmrcvrtrotiyv'"
421 ]
422 },
423 "execution_count": 22,
424 "metadata": {},
425 "output_type": "execute_result"
426 }
427 ],
428 "source": [
429 "polybius_decipher('lmcldlxcmxdldddlcdddldmdmx', '', order, order)"
430 ]
431 },
432 {
433 "cell_type": "code",
434 "execution_count": 23,
435 "metadata": {},
436 "outputs": [
437 {
438 "data": {
439 "text/plain": [
440 "'whileitistrue'"
441 ]
442 },
443 "execution_count": 23,
444 "metadata": {},
445 "output_type": "execute_result"
446 }
447 ],
448 "source": [
449 "polybius_decipher('lmcldlxcmxdldddlcdddldmdmx', '', order, order, column_first=True)"
450 ]
451 },
452 {
453 "cell_type": "code",
454 "execution_count": 24,
455 "metadata": {},
456 "outputs": [
457 {
458 "data": {
459 "text/plain": [
460 "'52232431152444244344424515'"
461 ]
462 },
463 "execution_count": 24,
464 "metadata": {},
465 "output_type": "execute_result"
466 }
467 ],
468 "source": [
469 "polybius_encipher('while it is true', '', '12345', '12345')"
470 ]
471 },
472 {
473 "cell_type": "code",
474 "execution_count": 25,
475 "metadata": {},
476 "outputs": [
477 {
478 "data": {
479 "text/plain": [
480 "'52232431152444244344424515'"
481 ]
482 },
483 "execution_count": 25,
484 "metadata": {},
485 "output_type": "execute_result"
486 }
487 ],
488 "source": [
489 "polybius_encipher('while it is true', '', [1, 2, 3, 4, 5], [1, 2, 3, 4, 5])"
490 ]
491 },
492 {
493 "cell_type": "code",
494 "execution_count": 26,
495 "metadata": {},
496 "outputs": [
497 {
498 "data": {
499 "text/plain": [
500 "'whileitistrue'"
501 ]
502 },
503 "execution_count": 26,
504 "metadata": {},
505 "output_type": "execute_result"
506 }
507 ],
508 "source": [
509 "polybius_decipher('52232431152444244344424515', '', [1, 2, 3, 4, 5], [1, 2, 3, 4, 5])"
510 ]
511 },
512 {
513 "cell_type": "code",
514 "execution_count": 27,
515 "metadata": {},
516 "outputs": [],
517 "source": [
518 "from multiprocessing import Pool\n",
519 "\n",
520 "def polybius_break_mp(message, column_labels, row_labels,\n",
521 " letters_to_merge=None,\n",
522 " wordlist=keywords, fitness=Pletters,\n",
523 " number_of_solutions=1, chunksize=500):\n",
524 " \"\"\"Breaks a Polybius substitution cipher using a dictionary and\n",
525 " frequency analysis\n",
526 "\n",
527 " >>> polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
528 " 'polybius decipherment', 'elephant', 'abcde', 'abcde'), \\\n",
529 " 'abcde', 'abcde', \\\n",
530 " wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS\n",
531 " (('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'abcde', False), \\\n",
532 " -54.5397...)\n",
533 " >>> polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
534 " 'polybius decipherment', 'elephant', 'abcde', 'abcde', column_first=True), \\\n",
535 " 'abcde', 'abcde', \\\n",
536 " wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS\n",
537 " (('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'abcde', True), \\\n",
538 " -54.5397...)\n",
539 " >>> polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
540 " 'polybius decipherment', 'elephant', 'abcde', 'abcde', column_first=False), \\\n",
541 " 'abcde', 'abcde', \\\n",
542 " wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS\n",
543 " (('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'abcde', False), \\\n",
544 " -54.5397...)\n",
545 " >>> polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
546 " 'polybius decipherment', 'elephant', 'abcde', 'pqrst', column_first=True), \\\n",
547 " 'abcde', 'pqrst', \\\n",
548 " wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS\n",
549 " (('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'pqrst', True), \\\n",
550 " -54.5397...)\n",
551 " \"\"\"\n",
552 " if letters_to_merge is None: \n",
553 " letters_to_m53880erge = {'j': 'i'}\n",
554 " with Pool() as pool:\n",
555 " helper_args = [(message, word, wrap, \n",
556 " column_labels, row_labels, column_first, \n",
557 " letters_to_merge, \n",
558 " fitness)\n",
559 " for word in wordlist\n",
560 " for wrap in KeywordWrapAlphabet\n",
561 " for column_first in [False, True]]\n",
562 " # Gotcha: the helper function here needs to be defined at the top level\n",
563 " # (limitation of Pool.starmap)\n",
564 " breaks = pool.starmap(polybius_break_worker, helper_args, chunksize)\n",
565 " if number_of_solutions == 1:\n",
566 " return max(breaks, key=lambda k: k[1])\n",
567 " else:\n",
568 " return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]\n",
569 "\n",
570 "def polybius_break_worker(message, keyword, wrap_alphabet, \n",
571 " column_order, row_order, column_first, \n",
572 " letters_to_merge, \n",
573 " fitness):\n",
574 " plaintext = polybius_decipher(message, keyword, \n",
575 " column_order, row_order, \n",
576 " column_first=column_first,\n",
577 " letters_to_merge=letters_to_merge, \n",
578 " wrap_alphabet=wrap_alphabet)\n",
579 " if plaintext:\n",
580 " fit = fitness(plaintext)\n",
581 " else:\n",
582 " fit = float('-inf')\n",
583 " logger.debug('Polybius break attempt using key {0} (wrap={1}, merging {2}), '\n",
584 " 'columns as {3}, rows as {4} (column_first={5}) '\n",
585 " 'gives fit of {6} and decrypt starting: '\n",
586 " '{7}'.format(keyword, wrap_alphabet, letters_to_merge,\n",
587 " column_order, row_order, column_first,\n",
588 " fit, sanitise(plaintext)[:50]))\n",
589 " return (keyword, wrap_alphabet, column_order, row_order, column_first), fit"
590 ]
591 },
592 {
593 "cell_type": "code",
594 "execution_count": 28,
595 "metadata": {},
596 "outputs": [
597 {
598 "name": "stdout",
599 "output_type": "stream",
600 "text": [
601 "CPU times: user 2.67 s, sys: 308 ms, total: 2.98 s\n",
602 "Wall time: 3min 58s\n"
603 ]
604 },
605 {
606 "data": {
607 "text/plain": [
608 "(('a', <KeywordWrapAlphabet.from_a: 1>, 'xlcdm', 'xlcdm', False),\n",
609 " -3018.8648333417113)"
610 ]
611 },
612 "execution_count": 28,
613 "metadata": {},
614 "output_type": "execute_result"
615 }
616 ],
617 "source": [
618 "%time polybius_break_mp(sanitise(cb), order, order)"
619 ]
620 },
621 {
622 "cell_type": "code",
623 "execution_count": 29,
624 "metadata": {},
625 "outputs": [
626 {
627 "data": {
628 "text/plain": [
629 "(('elephant',\n",
630 " <KeywordWrapAlphabet.from_a: 1>,\n",
631 " [1, 2, 3, 4, 5],\n",
632 " [1, 2, 3, 4, 5],\n",
633 " True),\n",
634 " -54.53880323982303)"
635 ]
636 },
637 "execution_count": 29,
638 "metadata": {},
639 "output_type": "execute_result"
640 }
641 ],
642 "source": [
643 "polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
644 " 'polybius decipherment', 'elephant', \\\n",
645 " [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], \\\n",
646 " KeywordWrapAlphabet.from_last), \\\n",
647 " [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], \\\n",
648 " wordlist=['cat', 'elephant', 'kangaroo'])"
649 ]
650 },
651 {
652 "cell_type": "code",
653 "execution_count": 30,
654 "metadata": {},
655 "outputs": [
656 {
657 "data": {
658 "text/plain": [
659 "'2214445544551522115522511155551543114252542214111352123234442355411135441314115451112122'"
660 ]
661 },
662 "execution_count": 30,
663 "metadata": {},
664 "output_type": "execute_result"
665 }
666 ],
667 "source": [
668 "polybius_encipher('this is a test message for the ' \\\n",
669 " 'polybius decipherment', 'elephant', \\\n",
670 " [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], \\\n",
671 " wrap_alphabet=KeywordWrapAlphabet.from_last)"
672 ]
673 },
674 {
675 "cell_type": "code",
676 "execution_count": 31,
677 "metadata": {},
678 "outputs": [
679 {
680 "data": {
681 "text/plain": [
682 "(('elephant',\n",
683 " <KeywordWrapAlphabet.from_last: 2>,\n",
684 " [1, 2, 3, 4, 5],\n",
685 " [1, 2, 3, 4, 5],\n",
686 " False),\n",
687 " -54.53880323982303)"
688 ]
689 },
690 "execution_count": 31,
691 "metadata": {},
692 "output_type": "execute_result"
693 }
694 ],
695 "source": [
696 "polybius_break_mp('2214445544551522115522511155551543114252542214111352123234442355411135441314115451112122', \\\n",
697 " [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], \\\n",
698 " wordlist=['cat', 'elephant', 'kangaroo'])"
699 ]
700 },
701 {
702 "cell_type": "code",
703 "execution_count": 32,
704 "metadata": {},
705 "outputs": [
706 {
707 "data": {
708 "text/plain": [
709 "'thisisatestmessageforthepolybiusdecipherment'"
710 ]
711 },
712 "execution_count": 32,
713 "metadata": {},
714 "output_type": "execute_result"
715 }
716 ],
717 "source": [
718 "polybius_decipher('2214445544551522115522511155551543114252542214111352123234442355411135441314115451112122', \\\n",
719 " 'elephant',\n",
720 " [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], \\\n",
721 " wrap_alphabet=KeywordWrapAlphabet.from_last)"
722 ]
723 },
724 {
725 "cell_type": "code",
726 "execution_count": 33,
727 "metadata": {},
728 "outputs": [
729 {
730 "data": {
731 "text/plain": [
732 "{(1, 1): 'e',\n",
733 " (1, 2): 'l',\n",
734 " (1, 3): 'p',\n",
735 " (1, 4): 'h',\n",
736 " (1, 5): 'a',\n",
737 " (2, 1): 'n',\n",
738 " (2, 2): 't',\n",
739 " (2, 3): 'b',\n",
740 " (2, 4): 'c',\n",
741 " (2, 5): 'd',\n",
742 " (3, 1): 'f',\n",
743 " (3, 2): 'g',\n",
744 " (3, 3): 'i',\n",
745 " (3, 4): 'k',\n",
746 " (3, 5): 'm',\n",
747 " (4, 1): 'o',\n",
748 " (4, 2): 'q',\n",
749 " (4, 3): 'r',\n",
750 " (4, 4): 's',\n",
751 " (4, 5): 'u',\n",
752 " (5, 1): 'v',\n",
753 " (5, 2): 'w',\n",
754 " (5, 3): 'x',\n",
755 " (5, 4): 'y',\n",
756 " (5, 5): 'z'}"
757 ]
758 },
759 "execution_count": 33,
760 "metadata": {},
761 "output_type": "execute_result"
762 }
763 ],
764 "source": [
765 "polybius_reverse_grid('elephant', [1, 2, 3, 4, 5], [1, 2, 3, 4, 5] )"
766 ]
767 },
768 {
769 "cell_type": "code",
770 "execution_count": 34,
771 "metadata": {},
772 "outputs": [
773 {
774 "data": {
775 "text/plain": [
776 "4"
777 ]
778 },
779 "execution_count": 34,
780 "metadata": {},
781 "output_type": "execute_result"
782 }
783 ],
784 "source": [
785 "type(2)('4')"
786 ]
787 },
788 {
789 "cell_type": "code",
790 "execution_count": 35,
791 "metadata": {},
792 "outputs": [
793 {
794 "data": {
795 "text/plain": [
796 "'bbadccddccddaebbaaddbbceaaddddaecbaacadadcbbadaaacdaabedbcccdeddbeaabdccacadaadcceaababb'"
797 ]
798 },
799 "execution_count": 35,
800 "metadata": {},
801 "output_type": "execute_result"
802 }
803 ],
804 "source": [
805 "polybius_encipher('this is a test message for the ' \\\n",
806 " 'polybius decipherment', 'elephant', 'abcde', 'abcde', column_first=False)"
807 ]
808 },
809 {
810 "cell_type": "code",
811 "execution_count": 36,
812 "metadata": {},
813 "outputs": [
814 {
815 "data": {
816 "text/plain": [
817 "'bbdaccddccddeabbaaddbbecaaddddeabcaaacadcdbbdaaacaadbadecbccedddebaadbcccadaaacdecaaabbb'"
818 ]
819 },
820 "execution_count": 36,
821 "metadata": {},
822 "output_type": "execute_result"
823 }
824 ],
825 "source": [
826 "polybius_encipher('this is a test message for the ' \\\n",
827 " 'polybius decipherment', 'elephant', 'abcde', 'abcde', column_first=True)"
828 ]
829 },
830 {
831 "cell_type": "code",
832 "execution_count": 37,
833 "metadata": {},
834 "outputs": [
835 {
836 "data": {
837 "text/plain": [
838 "'toisisvtestxessvbephktoefhnugiysweqifoekxelt'"
839 ]
840 },
841 "execution_count": 37,
842 "metadata": {},
843 "output_type": "execute_result"
844 }
845 ],
846 "source": [
847 "polybius_decipher('bbdaccddccddeabbaaddbbecaaddddeabcaaacadcdbbdaaacaadbadecbccedddebaadbcccadaaacdecaaabbb', 'elephant', 'abcde', 'abcde', column_first=False)"
848 ]
849 },
850 {
851 "cell_type": "code",
852 "execution_count": 38,
853 "metadata": {},
854 "outputs": [
855 {
856 "data": {
857 "text/plain": [
858 "'thisisatestmessageforthepolybiusdecipherment'"
859 ]
860 },
861 "execution_count": 38,
862 "metadata": {},
863 "output_type": "execute_result"
864 }
865 ],
866 "source": [
867 "polybius_decipher('bbdaccddccddeabbaaddbbecaaddddeabcaaacadcdbbdaaacaadbadecbccedddebaadbcccadaaacdecaaabbb', 'elephant', 'abcde', 'abcde', column_first=True)"
868 ]
869 },
870 {
871 "cell_type": "code",
872 "execution_count": 39,
873 "metadata": {
874 "scrolled": true
875 },
876 "outputs": [
877 {
878 "data": {
879 "text/plain": [
880 "(('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'abcde', False),\n",
881 " -54.53880323982303)"
882 ]
883 },
884 "execution_count": 39,
885 "metadata": {},
886 "output_type": "execute_result"
887 }
888 ],
889 "source": [
890 "polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
891 " 'polybius decipherment', 'elephant', 'abcde', 'abcde'), \\\n",
892 " 'abcde', 'abcde',\n",
893 " wordlist=['cat', 'elephant', 'kangaroo'])"
894 ]
895 },
896 {
897 "cell_type": "code",
898 "execution_count": 40,
899 "metadata": {
900 "scrolled": true
901 },
902 "outputs": [
903 {
904 "data": {
905 "text/plain": [
906 "(('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'abcde', True),\n",
907 " -54.53880323982303)"
908 ]
909 },
910 "execution_count": 40,
911 "metadata": {},
912 "output_type": "execute_result"
913 }
914 ],
915 "source": [
916 "polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
917 " 'polybius decipherment', 'elephant', 'abcde', 'abcde', column_first=True), \\\n",
918 " 'abcde', 'abcde',\n",
919 " wordlist=['cat', 'elephant', 'kangaroo'])"
920 ]
921 },
922 {
923 "cell_type": "code",
924 "execution_count": 41,
925 "metadata": {
926 "scrolled": true
927 },
928 "outputs": [
929 {
930 "data": {
931 "text/plain": [
932 "(('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'abcde', False),\n",
933 " -54.53880323982303)"
934 ]
935 },
936 "execution_count": 41,
937 "metadata": {},
938 "output_type": "execute_result"
939 }
940 ],
941 "source": [
942 "polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
943 " 'polybius decipherment', 'elephant', 'abcde', 'abcde', column_first=False), \\\n",
944 " 'abcde', 'abcde',\n",
945 " wordlist=['cat', 'elephant', 'kangaroo'])"
946 ]
947 },
948 {
949 "cell_type": "code",
950 "execution_count": 42,
951 "metadata": {
952 "scrolled": true
953 },
954 "outputs": [
955 {
956 "data": {
957 "text/plain": [
958 "(('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'pqrst', True),\n",
959 " -54.53880323982303)"
960 ]
961 },
962 "execution_count": 42,
963 "metadata": {},
964 "output_type": "execute_result"
965 }
966 ],
967 "source": [
968 "polybius_break_mp(polybius_encipher('this is a test message for the ' \\\n",
969 " 'polybius decipherment', 'elephant', 'abcde', 'pqrst', column_first=True), \\\n",
970 " 'abcde', 'pqrst',\n",
971 " wordlist=['cat', 'elephant', 'kangaroo'])"
972 ]
973 },
974 {
975 "cell_type": "code",
976 "execution_count": 43,
977 "metadata": {},
978 "outputs": [
979 {
980 "data": {
981 "text/plain": [
982 "'bwaycxdycxdyazbwavdybwczavdydyazcwavcvdvdxbwayavaxdvaweybxcxdzdybzavbycxaxayavdxczavbvbw'"
983 ]
984 },
985 "execution_count": 43,
986 "metadata": {},
987 "output_type": "execute_result"
988 }
989 ],
990 "source": [
991 "polybius_encipher('this is a test message for the ' \\\n",
992 " 'polybius decipherment', 'elephant', 'abcde', 'vwxyz')"
993 ]
994 },
995 {
996 "cell_type": "code",
997 "execution_count": 44,
998 "metadata": {},
999 "outputs": [
1000 {
1001 "data": {
1002 "text/plain": [
1003 "'thisisatestmessageforthepolybiusdecipherment'"
1004 ]
1005 },
1006 "execution_count": 44,
1007 "metadata": {},
1008 "output_type": "execute_result"
1009 }
1010 ],
1011 "source": [
1012 "polybius_decipher('bwaycxdycxdyazbwavdybwczavdydyazcwavcvdvdxbwayavaxdvaweybxcxdzdybzavbycxaxayavdxczavbvbw', \n",
1013 " 'elephant', 'abcde', 'vwxyz')"
1014 ]
1015 },
1016 {
1017 "cell_type": "code",
1018 "execution_count": 45,
1019 "metadata": {},
1020 "outputs": [],
1021 "source": [
1022 "logger.setLevel(logging.DEBUG)"
1023 ]
1024 },
1025 {
1026 "cell_type": "code",
1027 "execution_count": 46,
1028 "metadata": {},
1029 "outputs": [
1030 {
1031 "data": {
1032 "text/plain": [
1033 "(('elephant', <KeywordWrapAlphabet.from_a: 1>, 'abcde', 'vwxyz', False),\n",
1034 " -54.53880323982303)"
1035 ]
1036 },
1037 "execution_count": 46,
1038 "metadata": {},
1039 "output_type": "execute_result"
1040 }
1041 ],
1042 "source": [
1043 "polybius_break_mp('bwaycxdycxdyazbwavdybwczavdydyazcwavcvdvdxbwayavaxdvaweybxcxdzdybzavbycxaxayavdxczavbvbw', \\\n",
1044 " 'abcde', 'vwxyz',\n",
1045 " wordlist=['cat', 'elephant', 'kangaroo'])"
1046 ]
1047 },
1048 {
1049 "cell_type": "code",
1050 "execution_count": 47,
1051 "metadata": {},
1052 "outputs": [],
1053 "source": [
1054 "logger.debug('test')"
1055 ]
1056 },
1057 {
1058 "cell_type": "code",
1059 "execution_count": null,
1060 "metadata": {},
1061 "outputs": [],
1062 "source": []
1063 }
1064 ],
1065 "metadata": {
1066 "kernelspec": {
1067 "display_name": "Python 3",
1068 "language": "python",
1069 "name": "python3"
1070 },
1071 "language_info": {
1072 "codemirror_mode": {
1073 "name": "ipython",
1074 "version": 3
1075 },
1076 "file_extension": ".py",
1077 "mimetype": "text/x-python",
1078 "name": "python",
1079 "nbconvert_exporter": "python",
1080 "pygments_lexer": "ipython3",
1081 "version": "3.5.3"
1082 }
1083 },
1084 "nbformat": 4,
1085 "nbformat_minor": 2
1086 }