5 "execution_count": 125,
12 "from cipher.keyword_cipher import *\n",
13 "from support.utilities import *"
18 "execution_count": 11,
24 "'gpavtdyzocqnrsujmxikwbehlf'"
27 "execution_count": 11,
29 "output_type": "execute_result"
33 "pt = \"catch the cat\"\n",
35 "ca = list(string.ascii_lowercase)\n",
36 "random.shuffle(ca)\n",
43 "execution_count": 18,
52 "execution_count": 18,
54 "output_type": "execute_result"
58 "ct = keyword_encipher(pt, ca)\n",
64 "execution_count": 104,
68 "def show_mapping_alpha(c_a, p_a=string.ascii_lowercase, letters=string.ascii_lowercase):\n",
69 " mapping = {p: c for (p, c) in zip(p_a, c_a) if p in letters}\n",
70 " return show_mapping(mapping)\n",
72 "def show_mapping(mapping):\n",
73 " retval = '| plaintext letter | ' + ' | '.join(l for l in sorted(mapping)) + ' |\\n'\n",
74 " retval += '|-------------------|---|---|---|---|---|\\n'\n",
75 " retval += '| ciphertext letter | ' + ' | '.join(mapping[l] for l in sorted(mapping)) + ' |\\n'\n",
81 "execution_count": 105,
86 "output_type": "stream",
88 "| plaintext letter | a | c | e | h | t |\n",
89 "|-------------------|---|---|---|---|---|\n",
90 "| ciphertext letter | g | a | t | z | k |\n",
96 "print(show_mapping_alpha(ca, letters=sanitise(pt)))"
101 "execution_count": 17,
107 "({'a': 'g', 'c': 'a', 'e': 't', 'h': 'z', 't': 'k'},\n",
108 " {'g': 'a', 'a': 'c', 't': 'e', 'z': 'h', 'k': 't'})"
111 "execution_count": 17,
113 "output_type": "execute_result"
117 "m0 = {p: c for (p, c) in zip(string.ascii_letters, ca) if p in pt}\n",
118 "im0 = {c: p for (p, c) in zip(string.ascii_letters, ca) if p in pt}\n",
124 "execution_count": 55,
129 "output_type": "stream",
131 "| a | c | e | h | t |\n",
132 "| g | a | t | z | k |\n",
138 "print(show_mapping(m0))"
143 "execution_count": 61,
147 "def apply_inverse_map(ciphertext, mapping):\n",
148 " plaintext = cat(mapping[l] if l in mapping else l for l in ciphertext)\n",
149 " return plaintext, Pbigrams(sanitise(plaintext))"
154 "execution_count": 44,
158 "def swap(letters, i, j):\n",
164 " return (letters[:i] + letters[j] + letters[i+1:j] + letters[i] +\n",
170 "execution_count": 50,
174 "def map_swap(mapping):\n",
175 " keys = sorted(mapping)\n",
176 " values = cat(mapping[l] for l in keys)\n",
178 " swapped_values = swap(values, random.randrange(n), random.randrange(n))\n",
179 " return {k: sv for (k, sv) in zip(keys, swapped_values)}"
184 "execution_count": 89,
188 "im1 = map_swap(im0)\n",
189 "im2 = map_swap(im1)"
194 "execution_count": 90,
200 "('aceah eht ace', -24.470656262279007)"
203 "execution_count": 90,
205 "output_type": "execute_result"
209 "apply_inverse_map(ct, im2)"
214 "execution_count": 91,
220 "('actah the act', -23.337953804339712)"
223 "execution_count": 91,
225 "output_type": "execute_result"
229 "apply_inverse_map(ct, im1)"
234 "execution_count": 88,
240 "('catch the cat', -22.142275954584633)"
243 "execution_count": 88,
245 "output_type": "execute_result"
249 "apply_inverse_map(ct, im0)"
254 "execution_count": 92,
260 "({'g': 'a', 'a': 'c', 't': 'e', 'z': 'h', 'k': 't'},\n",
261 " {'a': 'a', 'g': 'c', 'k': 't', 't': 'e', 'z': 'h'},\n",
262 " {'a': 'a', 'g': 'c', 'k': 'e', 't': 't', 'z': 'h'})"
265 "execution_count": 92,
267 "output_type": "execute_result"
276 "execution_count": 93,
280 "m1 = {im1[l]: l for l in im1}\n",
281 "m2 = {im2[l]: l for l in im2}"
286 "execution_count": 106,
291 "output_type": "stream",
293 "| plaintext letter | a | c | e | h | t |\n",
294 "|-------------------|---|---|---|---|---|\n",
295 "| ciphertext letter | g | a | t | z | k |\n",
301 "print(show_mapping(m0))"
306 "execution_count": 107,
311 "output_type": "stream",
313 "| plaintext letter | a | c | e | h | t |\n",
314 "|-------------------|---|---|---|---|---|\n",
315 "| ciphertext letter | a | g | t | z | k |\n",
321 "print(show_mapping(m1))"
326 "execution_count": 108,
331 "output_type": "stream",
333 "| plaintext letter | a | c | e | h | t |\n",
334 "|-------------------|---|---|---|---|---|\n",
335 "| ciphertext letter | a | g | k | z | t |\n",
341 "print(show_mapping(m2))"
346 "execution_count": 110,
352 "('hceha eat hce', -26.41716766077668)"
355 "execution_count": 110,
357 "output_type": "execute_result"
361 "im3 = map_swap(im2)\n",
362 "apply_inverse_map(ct, im3)"
367 "execution_count": 111,
371 "m3 = {im3[l]: l for l in im3}"
376 "execution_count": 112,
381 "output_type": "stream",
383 "| plaintext letter | a | c | e | h | t |\n",
384 "|-------------------|---|---|---|---|---|\n",
385 "| ciphertext letter | z | g | k | a | t |\n",
391 "print(show_mapping(m3))"
396 "execution_count": 113,
400 "def all_swaps(mapping):\n",
401 " keys = sorted(mapping)\n",
402 " values = cat(mapping[l] for l in keys)\n",
404 " swapped_values = [swap(values, i, j) for i in range(n) for j in range(n) if i < j]\n",
405 " return [{k: sv for (k, sv) in zip(keys, svs)} for svs in swapped_values]"
410 "execution_count": 117,
416 "({'g': 'a', 'a': 'c', 't': 'e', 'z': 'h', 'k': 't'},\n",
417 " [('actah the act', -23.337953804339712),\n",
418 " ('tacth che tac', -22.992889593694795),\n",
419 " ('eateh thc eat', -23.337174988961543),\n",
420 " ('hathc tce hat', -24.20565798548872),\n",
421 " ('ctach ahe cta', -23.361982341471602),\n",
422 " ('cetch tha cet', -23.152196785128968),\n",
423 " ('chtca tae cht', -25.47053856384374),\n",
424 " ('caech eht cae', -27.119008761052356),\n",
425 " ('cahct hte cah', -25.96020844569102),\n",
426 " ('catce teh cat', -24.369461369323975)])"
429 "execution_count": 117,
431 "output_type": "execute_result"
435 "im0, [apply_inverse_map(ct, tim) for tim in all_swaps(im0)]"
440 "execution_count": 118,
446 "({'a': 'a', 'g': 'c', 'k': 'e', 't': 't', 'z': 'h'},\n",
447 " [('caech eht cae', -27.119008761052356),\n",
448 " ('ecaeh aht eca', -26.10317913928645),\n",
449 " ('tceth eha tce', -23.289877585658743),\n",
450 " ('hceha eat hce', -26.41716766077668),\n",
451 " ('aecah cht aec', -28.466074945814817),\n",
452 " ('ateah ehc ate', -23.89678491033435),\n",
453 " ('aheac ect ahe', -23.82052347276842),\n",
454 " ('actah the act', -23.337953804339712),\n",
455 " ('achae het ach', -24.4061387567535),\n",
456 " ('aceat eth ace', -21.139211036323402)])"
459 "execution_count": 118,
461 "output_type": "execute_result"
465 "im2, [apply_inverse_map(ct, tim) for tim in all_swaps(im2)]"
470 "execution_count": 119,
474 "def all_swaps_worse(mapping):\n",
475 " _, score0 = apply_inverse_map(ct, mapping)\n",
476 " swapped_mappings = all_swaps(mapping)\n",
477 " scores = [apply_inverse_map(ct, m)[1] for m in swapped_mappings]\n",
478 " better_scores = [s for s in scores if s > score0]\n",
479 " return better_scores == []"
484 "execution_count": 123,
493 "execution_count": 123,
495 "output_type": "execute_result"
499 "all_swaps_worse(im3)"
504 "execution_count": 124,
508 "def make_map(als, bls):\n",
509 " return {a: b for (a, b) in zip(als, bls)}"
514 "execution_count": 129,
523 "execution_count": 129,
525 "output_type": "execute_result"
529 "ptls = cat(sorted(deduplicate(sanitise(pt))))\n",
530 "ctls = cat(sorted(deduplicate(sanitise(ct))))\n",
536 "execution_count": 132,
543 " [{'a': 'a', 'g': 'c', 'k': 'e', 't': 'h', 'z': 't'},\n",
544 " {'a': 'a', 'g': 'c', 'k': 'e', 'z': 'h', 't': 't'},\n",
545 " {'a': 'a', 'g': 'c', 't': 'e', 'k': 'h', 'z': 't'},\n",
546 " {'a': 'a', 'g': 'c', 't': 'e', 'z': 'h', 'k': 't'},\n",
547 " {'a': 'a', 'g': 'c', 'z': 'e', 'k': 'h', 't': 't'}])"
550 "execution_count": 132,
552 "output_type": "execute_result"
556 "all_maps = [make_map(c, ptls) for c in itertools.permutations(ctls)]\n",
557 "len(all_maps), all_maps[:5]"
562 "execution_count": 138,
568 "[{'a': 'a', 'z': 'c', 'k': 'e', 't': 'h', 'g': 't'},\n",
569 " {'g': 'a', 't': 'c', 'z': 'e', 'a': 'h', 'k': 't'},\n",
570 " {'g': 'a', 'z': 'c', 'a': 'e', 't': 'h', 'k': 't'},\n",
571 " {'t': 'a', 'k': 'c', 'g': 'e', 'z': 'h', 'a': 't'},\n",
572 " {'t': 'a', 'z': 'c', 'k': 'e', 'g': 'h', 'a': 't'},\n",
573 " {'z': 'a', 't': 'c', 'a': 'e', 'k': 'h', 'g': 't'}]"
576 "execution_count": 138,
578 "output_type": "execute_result"
582 "local_optima = [m for m in all_maps if all_swaps_worse(m) if m != im0]\n",
588 "execution_count": 143,
594 "(('tecth cha tec', -22.37718617528681),\n",
595 " [('etceh cha etc', -27.45222919076422),\n",
596 " ('cetch tha cet', -23.152196785128968),\n",
597 " ('aecah cht aec', -28.466074945814817),\n",
598 " ('hecht cta hec', -24.0528877258752),\n",
599 " ('tceth eha tce', -23.289877585658743),\n",
600 " ('tacth che tac', -22.992889593694795),\n",
601 " ('thcte cea thc', -23.37530629522044),\n",
602 " ('teath ahc tea', -23.192822966291835),\n",
603 " ('tehtc hca teh', -25.824045558109102),\n",
604 " ('tecta cah tec', -23.630623398955464)])"
607 "execution_count": 143,
609 "output_type": "execute_result"
613 "apply_inverse_map(ct, local_optima[3]), [apply_inverse_map(ct, tim) for tim in all_swaps(local_optima[3])]"
618 "execution_count": 145,
624 "(('ethea hac eth', -21.831799648932474),\n",
625 " [('tehta hac teh', -25.2630658238322),\n",
626 " ('hteha eac hte', -25.12161519433393),\n",
627 " ('cthca hae cth', -25.56645047924706),\n",
628 " ('athae hec ath', -22.523920547555058),\n",
629 " ('ehtea tac eht', -24.414224893001006),\n",
630 " ('echea hat ech', -22.34614937355321),\n",
631 " ('eahet htc eah', -24.64789885786501),\n",
632 " ('etcea cah etc', -24.40643936994998),\n",
633 " ('etaeh ahc eta', -27.042650227267693),\n",
634 " ('ethec hca eth', -23.70218668022281)])"
637 "execution_count": 145,
639 "output_type": "execute_result"
643 "apply_inverse_map(ct, local_optima[5]), [apply_inverse_map(ct, tim) for tim in all_swaps(local_optima[5])]"
648 "execution_count": 140,
654 "('catch the cat', -22.142275954584633)"
657 "execution_count": 140,
659 "output_type": "execute_result"
663 "apply_inverse_map(ct, im0)"
668 "execution_count": 146,
674 "{'t': 'a', 'k': 'c', 'g': 'e', 'z': 'h', 'a': 't'}"
677 "execution_count": 146,
679 "output_type": "execute_result"
688 "execution_count": 147,
693 "output_type": "stream",
695 "| plaintext letter | a | c | e | h | t |\n",
696 "|-------------------|---|---|---|---|---|\n",
697 "| ciphertext letter | t | k | g | z | a |\n",
703 "l3 = {local_optima[3][l]: l for l in local_optima[3]}\n",
704 "print(show_mapping(l3))"
709 "execution_count": 150,
715 "'etoainhsrdlumwycfgpbvkxjqz'"
718 "execution_count": 150,
720 "output_type": "execute_result"
724 "cat(p[0] for p in english_counts.most_common())"
729 "execution_count": null,
737 "display_name": "Python 3",
738 "language": "python",
746 "file_extension": ".py",
747 "mimetype": "text/x-python",
749 "nbconvert_exporter": "python",
750 "pygments_lexer": "ipython3",