12 "import collections\n",
13 "import multiprocessing\n",
15 "from enigma import *"
26 "Signal = collections.namedtuple('Signal', ['bank', 'wire'])\n",
27 "Connection = collections.namedtuple('Connection', ['banks', 'scrambler'])\n",
28 "MenuItem = collections.namedtuple('MenuIem', ['before', 'after', 'number'])"
39 "class Scrambler(object):\n",
40 " def __init__(self, wheel1_spec, wheel2_spec, wheel3_spec, reflector_spec,\n",
41 " wheel1_pos='a', wheel2_pos='a', wheel3_pos='a'):\n",
42 " self.wheel1 = SimpleWheel(wheel1_spec, position=wheel1_pos)\n",
43 " self.wheel2 = SimpleWheel(wheel2_spec, position=wheel2_pos)\n",
44 " self.wheel3 = SimpleWheel(wheel3_spec, position=wheel3_pos)\n",
45 " self.reflector = Reflector(reflector_spec)\n",
47 " def __getattribute__(self, name):\n",
48 " if name=='wheel_positions':\n",
49 " return self.wheel1.position, self.wheel2.position, self.wheel3.position \n",
50 " elif name=='wheel_positions_l':\n",
51 " return self.wheel1.position_l, self.wheel2.position_l, self.wheel3.position_l \n",
53 " return object.__getattribute__(self, name)\n",
55 " def advance(self, wheel1=False, wheel2=False, wheel3=True):\n",
56 " if wheel1: self.wheel1.advance()\n",
57 " if wheel2: self.wheel2.advance()\n",
58 " if wheel3: self.wheel3.advance()\n",
60 " def lookup(self, letter):\n",
61 " a = self.wheel3.forward(letter)\n",
62 " b = self.wheel2.forward(a)\n",
63 " c = self.wheel1.forward(b)\n",
64 " d = self.reflector.forward(c)\n",
65 " e = self.wheel1.backward(d)\n",
66 " f = self.wheel2.backward(e)\n",
67 " g = self.wheel3.backward(f)\n",
70 " def set_positions(self, wheel1_pos, wheel2_pos, wheel3_pos):\n",
71 " self.wheel1.set_position(wheel1_pos)\n",
72 " self.wheel2.set_position(wheel2_pos)\n",
73 " self.wheel3.set_position(wheel3_pos) "
84 "class Bombe(object):\n",
86 " def __init__(self, wheel1_spec, wheel2_spec, wheel3_spec, reflector_spec,\n",
87 " menu=None, start_signal=None, use_diagonal_board=True, \n",
88 " verify_plugboard=True):\n",
89 " self.connections = []\n",
90 " self.wheel1_spec = wheel1_spec\n",
91 " self.wheel2_spec = wheel2_spec\n",
92 " self.wheel3_spec = wheel3_spec\n",
93 " self.reflector_spec = reflector_spec\n",
95 " self.read_menu(menu)\n",
96 " if start_signal:\n",
97 " self.test_start = start_signal\n",
98 " self.use_diagonal_board = use_diagonal_board\n",
99 " self.verify_plugboard = verify_plugboard\n",
101 " def __getattribute__(self, name):\n",
102 " if name=='wheel_positions':\n",
103 " return self.connections[0].scrambler.wheel_positions\n",
104 " elif name=='wheel_positions_l':\n",
105 " return self.connections[0].scrambler.wheel_positions_l\n",
107 " return object.__getattribute__(self, name)\n",
109 " def __call__(self, start_positions):\n",
110 " return start_positions, self.test(initial_signal=self.test_start,\n",
111 " start_positions=start_positions, \n",
112 " use_diagonal_board=self.use_diagonal_board,\n",
113 " verify_plugboard=self.verify_plugboard)\n",
115 " def add_connection(self, bank_before, bank_after, scrambler):\n",
116 " self.connections += [Connection([bank_before, bank_after], scrambler)]\n",
118 " def read_menu(self, menu):\n",
119 " for item in menu:\n",
120 " scrambler = Scrambler(self.wheel1_spec, self.wheel2_spec, self.wheel3_spec,\n",
121 " self.reflector_spec,\n",
122 " wheel3_pos=unpos(item.number - 1))\n",
123 " self.add_connection(item.before, item.after, scrambler)\n",
124 " most_common_letter = (collections.Counter(m.before for m in menu) + \\\n",
125 " collections.Counter(m.after for m in menu)).most_common(1)[0][0]\n",
126 " self.test_start = Signal(most_common_letter, most_common_letter)\n",
128 " def set_positions(self, wheel1_pos, wheel2_pos, wheel3_pos):\n",
129 " for i, c in enumerate(self.connections):\n",
130 " c.scrambler.set_positions(wheel1_pos, wheel2_pos, unpos(pos(wheel3_pos) + i))\n",
132 " def test(self, initial_signal=None, start_positions=None, use_diagonal_board=True,\n",
133 " verify_plugboard=True):\n",
134 " self.banks = {label: \n",
135 " dict(zip(string.ascii_lowercase, [False]*len(string.ascii_lowercase)))\n",
136 " for label in string.ascii_lowercase}\n",
137 " if start_positions:\n",
138 " self.set_positions(*start_positions)\n",
139 " if not initial_signal:\n",
140 " initial_signal = self.test_start\n",
141 " self.pending = [initial_signal]\n",
142 " self.propagate(use_diagonal_board)\n",
143 " live_wire_count = len([self.banks[self.test_start.bank][w] \n",
144 " for w in self.banks[self.test_start.bank] \n",
145 " if self.banks[self.test_start.bank][w]])\n",
146 " if live_wire_count < 26:\n",
147 " if verify_plugboard:\n",
148 " possibles = self.possible_plugboards()\n",
149 " return all(s0.isdisjoint(s1) for s0 in possibles for s1 in possibles if s0 != s1)\n",
155 " def propagate(self, use_diagonal_board):\n",
156 " while self.pending:\n",
157 " current = self.pending[0]\n",
158 " # print(\"processing\", current)\n",
159 " self.pending = self.pending[1:]\n",
160 " if not self.banks[current.bank][current.wire]:\n",
161 " self.banks[current.bank][current.wire] = True\n",
162 " if use_diagonal_board:\n",
163 " self.pending += [Signal(current.wire, current.bank)]\n",
164 " for c in self.connections:\n",
165 " if current.bank in c.banks:\n",
166 " other_bank = [b for b in c.banks if b != current.bank][0]\n",
167 " other_wire = c.scrambler.lookup(current.wire)\n",
168 " # print(\" adding\", other_bank, other_wire, \"because\", c.banks)\n",
169 " self.pending += [Signal(other_bank, other_wire)]\n",
171 " def run(self, run_start=None, wheel1_pos='a', wheel2_pos='a', wheel3_pos='a', use_diagonal_board=True):\n",
172 " if not run_start:\n",
173 " run_start = self.test_start\n",
174 " self.solutions = []\n",
175 " self.set_positions(wheel1_pos, wheel2_pos, wheel3_pos)\n",
176 " for run_index in range(26*26*26):\n",
177 " if self.test(initial_signal=run_start, use_diagonal_board=use_diagonal_board):\n",
178 " self.solutions += [self.connections[0].scrambler.wheel_positions_l]\n",
179 " advance3 = True\n",
180 " advance2 = False\n",
181 " advance1 = False\n",
182 " if (run_index + 1) % 26 == 0: advance2 = True\n",
183 " if (run_index + 1) % (26*26) == 0: advance1 = True\n",
184 " for c in self.connections:\n",
185 " c.scrambler.advance(advance1, advance2, advance3)\n",
186 " return self.solutions\n",
188 " def possible_plugboards(self):\n",
189 " possibles = set()\n",
190 " for b in self.banks:\n",
191 " active = [w for w in self.banks[b] if self.banks[b][w]]\n",
192 " inactive = [w for w in self.banks[b] if not self.banks[b][w]]\n",
193 " if len(active) == 1:\n",
194 " possibles = possibles.union({frozenset((b, active[0]))})\n",
195 " if len(inactive) == 1:\n",
196 " possibles = possibles.union({frozenset((b, inactive[0]))})\n",
197 " return possibles\n"
202 "execution_count": 5,
208 "bombe = Bombe(wheel_i_spec, wheel_ii_spec, wheel_iii_spec, reflector_b_spec)\n",
209 "# len(bombe.banks), bombe.banks['a'] == bombe.banks['b']"
214 "execution_count": 6,
220 "test_enigma = Enigma(reflector_b_spec, \n",
221 " wheel_i_spec, wheel_i_pegs,\n",
222 " wheel_ii_spec, wheel_ii_pegs,\n",
223 " wheel_iii_spec, wheel_iii_pegs,\n",
230 "execution_count": 7,
238 "'opgndxcrwomnlnecjz'"
241 "execution_count": 7,
243 "output_type": "execute_result"
247 "test_enigma.set_wheels('a', 'a', 'a')\n",
248 "pt = 'thisisatestmessage'\n",
249 "ct = test_enigma.encipher(pt)\n",
255 "execution_count": 8,
266 "execution_count": 8,
268 "output_type": "execute_result"
272 "cat(test_enigma.wheel_positions_l)"
277 "execution_count": 9,
285 "[MenuIem(before='t', after='o', number=1),\n",
286 " MenuIem(before='h', after='p', number=2),\n",
287 " MenuIem(before='i', after='g', number=3),\n",
288 " MenuIem(before='s', after='n', number=4),\n",
289 " MenuIem(before='i', after='d', number=5),\n",
290 " MenuIem(before='s', after='x', number=6),\n",
291 " MenuIem(before='a', after='c', number=7),\n",
292 " MenuIem(before='t', after='r', number=8),\n",
293 " MenuIem(before='e', after='w', number=9),\n",
294 " MenuIem(before='s', after='o', number=10),\n",
295 " MenuIem(before='t', after='m', number=11),\n",
296 " MenuIem(before='m', after='n', number=12),\n",
297 " MenuIem(before='e', after='l', number=13),\n",
298 " MenuIem(before='s', after='n', number=14),\n",
299 " MenuIem(before='s', after='e', number=15),\n",
300 " MenuIem(before='a', after='c', number=16),\n",
301 " MenuIem(before='g', after='j', number=17),\n",
302 " MenuIem(before='e', after='z', number=18)]"
305 "execution_count": 9,
307 "output_type": "execute_result"
311 "menu = [MenuItem(p, c, i+1) for i, (p, c) in enumerate(zip(pt, ct))]\n",
317 "execution_count": 10,
323 "def make_menu(plaintext, ciphertext):\n",
324 " return [MenuItem(p, c, i+1) \n",
325 " for i, (p, c) in enumerate(zip(plaintext, ciphertext))]"
330 "execution_count": 11,
338 "[MenuIem(before='t', after='o', number=1),\n",
339 " MenuIem(before='h', after='p', number=2),\n",
340 " MenuIem(before='i', after='g', number=3),\n",
341 " MenuIem(before='s', after='n', number=4),\n",
342 " MenuIem(before='i', after='d', number=5),\n",
343 " MenuIem(before='s', after='x', number=6),\n",
344 " MenuIem(before='a', after='c', number=7),\n",
345 " MenuIem(before='t', after='r', number=8),\n",
346 " MenuIem(before='e', after='w', number=9),\n",
347 " MenuIem(before='s', after='o', number=10),\n",
348 " MenuIem(before='t', after='m', number=11),\n",
349 " MenuIem(before='m', after='n', number=12),\n",
350 " MenuIem(before='e', after='l', number=13),\n",
351 " MenuIem(before='s', after='n', number=14),\n",
352 " MenuIem(before='s', after='e', number=15),\n",
353 " MenuIem(before='a', after='c', number=16),\n",
354 " MenuIem(before='g', after='j', number=17),\n",
355 " MenuIem(before='e', after='z', number=18)]"
358 "execution_count": 11,
360 "output_type": "execute_result"
369 "execution_count": 12,
380 "execution_count": 12,
382 "output_type": "execute_result"
386 "(collections.Counter(m.before for m in menu) + collections.Counter(m.after for m in menu)).most_common(1)[0][0]"
391 "execution_count": 13,
397 "bombe.read_menu(menu)"
402 "execution_count": 14,
413 "execution_count": 14,
415 "output_type": "execute_result"
419 "len(bombe.connections)"
424 "execution_count": 15,
431 "output_type": "stream",
455 "for c in bombe.connections:\n",
456 " print(c.banks, cat(c.scrambler.wheel_positions_l))"
461 "execution_count": 16,
472 "execution_count": 16,
474 "output_type": "execute_result"
478 "bombe.test(Signal('t', 't'))"
483 "execution_count": 17,
519 "execution_count": 17,
521 "output_type": "execute_result"
530 "execution_count": 18,
537 "output_type": "stream",
539 "a : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
540 "b : AbCDEfGHIJkLMNOPqRSTuvWXyZ\n",
541 "c : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
542 "d : ABCDEFGHIJKLMNOPQRSTUVWXyZ\n",
543 "e : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
544 "f : AbCDEfGHIJkLMNOPqRSTuvWXyZ\n",
545 "g : ABCDEFGHIJKLMNOPQRSTuVWXYZ\n",
546 "h : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
547 "i : ABCDEFGHIJKLMNOPQRSTUvWXYZ\n",
548 "j : ABCDEFGHIjKLMNOPQRSTUVWXYZ\n",
549 "k : AbCDEfGHIJkLMNOPqRSTuvWXyZ\n",
550 "l : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
551 "m : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
552 "n : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
553 "o : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
554 "p : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
555 "q : AbCDEfGHIJkLMNOPqRSTuvWXyZ\n",
556 "r : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
557 "s : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
558 "t : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
559 "u : AbCDEfgHIJkLMNOPqRSTuvWXyZ\n",
560 "v : AbCDEfGHiJkLMNOPqRSTuvWXyZ\n",
561 "w : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
562 "x : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
563 "y : AbCdEfGHIJkLMNOPqRSTuvWXyZ\n",
564 "z : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
569 "for b in sorted(bombe.banks):\n",
570 " print(b, ': ', end='')\n",
571 " for w in sorted(bombe.banks[b]):\n",
572 " if bombe.banks[b][w]:\n",
573 " print(w.upper(), end='')\n",
575 " print(w, end='')\n",
581 "execution_count": 19,
592 "execution_count": 19,
594 "output_type": "execute_result"
598 "bombe.wheel_positions_l"
603 "execution_count": 20,
610 "output_type": "stream",
634 "bombe.set_positions('p', 'q', 'r')\n",
635 "for c in bombe.connections:\n",
636 " print(c.banks, cat(c.scrambler.wheel_positions_l))"
641 "execution_count": 21,
653 "execution_count": 22,
660 "output_type": "stream",
662 "a : .b.defghijklmnopqrstuvwxyz\n",
663 "b : a.cde.ghij.lmnop.rst..wx.z\n",
664 "c : .b.defghijklmnopqrstuvwxyz\n",
665 "d : abc.e.gh.jklmnopqrstuvwxyz\n",
666 "e : abcd.fghijklmnopqrstuvwxyz\n",
667 "f : a.c.e.g.ij.lmno..rst..wx.z\n",
668 "g : abcdef.h..klmnopqrstuvwxyz\n",
669 "h : abcde.g.ij.lmno.qrst..wxyz\n",
670 "i : abc.ef.h.jklmnopqrstuvwxyz\n",
671 "j : abcdef.hi.klmnopqrstuvwx.z\n",
672 "k : a.cde.g.ij.lmno..rst..wx.z\n",
673 "l : abcdefghijk.mnopqrstuvwxyz\n",
674 "m : abcdefghijkl.nopqrstuvwxyz\n",
675 "n : abcdefghijklm.opqrstuvwxyz\n",
676 "o : abcdefghijklmn.pqrstuvwxyz\n",
677 "p : abcde.g.ij.lmno.qrst..wxyz\n",
678 "q : a.cde.ghij.lmnop.rst..wx.z\n",
679 "r : abcdefghijklmnopq.stuvwxyz\n",
680 "s : abcdefghijklmnopqr.tuvwxyz\n",
681 "t : abcdefghijklmnopqrs.uvwxyz\n",
682 "u : a.cde.g.ij.lmno..rst..wx.z\n",
683 "v : a.cde.g.ij.lmno..rst..wx.z\n",
684 "w : abcdefghijklmnopqrstuv.xyz\n",
685 "x : abcdefghijklmnopqrstuvw.yz\n",
686 "y : a.cde.ghi..lmnop.rst..wx.z\n",
687 "z : abcdefghijklmnopqrstuvwxy.\n"
692 "bombe.set_positions('a', 'a', 'b')\n",
693 "bombe.test(Signal('s', 'a'))\n",
695 "for b in sorted(bombe.banks):\n",
696 " print(b, ': ', end='')\n",
697 " for w in sorted(bombe.banks[b]):\n",
698 " if bombe.banks[b][w]:\n",
699 " print(w, end='')\n",
701 " print('.', end='')\n",
707 "execution_count": 23,
714 "output_type": "stream",
716 "a : ..........................\n",
717 "b : ..........................\n",
718 "c : ..........................\n",
719 "d : ..........................\n",
720 "e : ....e.....................\n",
721 "f : ..........................\n",
722 "g : ..........................\n",
723 "h : ..........................\n",
724 "i : ..........................\n",
725 "j : ..........................\n",
726 "k : ..........................\n",
727 "l : ...........l..............\n",
728 "m : ............m.............\n",
729 "n : .............n............\n",
730 "o : ..............o...........\n",
731 "p : ..........................\n",
732 "q : ..........................\n",
733 "r : .................r........\n",
734 "s : ..................s.......\n",
735 "t : ...................t......\n",
736 "u : ..........................\n",
737 "v : ..........................\n",
738 "w : ......................w...\n",
739 "x : .......................x..\n",
740 "y : ..........................\n",
741 "z : .........................z\n"
746 "bombe.set_positions('a', 'a', 'b')\n",
749 "for b in sorted(bombe.banks):\n",
750 " print(b, ': ', end='')\n",
751 " for w in sorted(bombe.banks[b]):\n",
752 " if bombe.banks[b][w]:\n",
753 " print(w, end='')\n",
755 " print('.', end='')\n",
761 "execution_count": 24,
772 "execution_count": 24,
774 "output_type": "execute_result"
778 "len([bombe.banks['t'][w] for w in bombe.banks['t'] if bombe.banks['t'][w]])"
783 "execution_count": 25,
790 "# results = bombe.run()\n",
791 "# print(len(results), ('a', 'a', 'b') in results)"
796 "execution_count": 26,
803 "# results = bombe.run(use_diagonal_board=False)\n",
804 "# print(len(results), ('a', 'a', 'b') in results)"
809 "execution_count": 27,
820 "execution_count": 27,
822 "output_type": "execute_result"
826 "bombe.wheel_positions_l"
831 "execution_count": 28,
842 "execution_count": 28,
844 "output_type": "execute_result"
848 "bombe.test(Signal('t', 't'), ('p', 'p', 'p'))"
853 "execution_count": 29,
864 "execution_count": 29,
866 "output_type": "execute_result"
870 "bombe.wheel_positions_l"
875 "execution_count": 30,
882 "output_type": "stream",
884 "a : abcdefghijklmnop.rst.vwxyz\n",
885 "b : a.cde.g.ij.lmno..rst..wx.z\n",
886 "c : abcdefghijklmnop.rst.vwxyz\n",
887 "d : abcdefghijklmnopqrstuvwxyz\n",
888 "e : abcdefghijklmnopqrstuvwxyz\n",
889 "f : a.cde.g.ij.lmno..rst..wx.z\n",
890 "g : abcdefghijklmnopqrstuvwxyz\n",
891 "h : a.cde.ghijklmnop.rst.vwxyz\n",
892 "i : abcdefghijklmnopqrstuvwxyz\n",
893 "j : abcdefghijklmnopqrstuvwxyz\n",
894 "k : a.cde.ghij.lmnop.rst..wx.z\n",
895 "l : abcdefghijklmnopqrstuvwxyz\n",
896 "m : abcdefghijklmnopqrstuvwxyz\n",
897 "n : abcdefghijklmnopqrstuvwxyz\n",
898 "o : abcdefghijklmnopqrstuvwxyz\n",
899 "p : a.cde.ghijklmnop.rst.vwxyz\n",
900 "q : ...de.g.ij.lmno..rst..wx.z\n",
901 "r : abcdefghijklmnopqrstuvwxyz\n",
902 "s : abcdefghijklmnopqrstuvwxyz\n",
903 "t : abcdefghijklmnopqrstuvwxyz\n",
904 "u : ...de.g.ij.lmno..rst..wx.z\n",
905 "v : a.cde.ghij.lmnop.rst..wx.z\n",
906 "w : abcdefghijklmnopqrstuvwxyz\n",
907 "x : abcdefghijklmnopqrstuvwxyz\n",
908 "y : a.cde.ghij.lmnop.rst..wx.z\n",
909 "z : abcdefghijklmnopqrstuvwxyz\n"
914 "for b in sorted(bombe.banks):\n",
915 " print(b, ': ', end='')\n",
916 " for w in sorted(bombe.banks[b]):\n",
917 " if bombe.banks[b][w]:\n",
918 " print(w, end='')\n",
920 " print('.', end='')\n",
926 "execution_count": 31,
937 "execution_count": 31,
939 "output_type": "execute_result"
943 "allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
944 "len(list(allwheels))"
949 "execution_count": 32,
957 "(('a', 'a', 'b'), True)"
960 "execution_count": 32,
962 "output_type": "execute_result"
966 "b = Bombe(wheel_i_spec, wheel_ii_spec, wheel_iii_spec, reflector_b_spec, menu=menu)\n",
972 "execution_count": 33,
978 "b = Bombe(wheel_i_spec, wheel_ii_spec, wheel_iii_spec, reflector_b_spec, menu=menu)(('a', 'a', 'b'))"
983 "execution_count": 34,
994 "execution_count": 34,
996 "output_type": "execute_result"
1000 "allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1002 "with multiprocessing.Pool() as pool:\n",
1003 " res = pool.map(Bombe(wheel_i_spec, wheel_ii_spec, wheel_iii_spec, reflector_b_spec, menu=menu),\n",
1005 "[r[0] for r in res if r[1]]"
1009 "cell_type": "code",
1010 "execution_count": 35,
1016 "def run_multi_bombe(wheel1_spec, wheel2_spec, wheel3_spec, reflector_spec, menu,\n",
1017 " start_signal=None, use_diagonal_board=True, \n",
1018 " verify_plugboard=True):\n",
1019 " allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1021 " with multiprocessing.Pool() as pool:\n",
1022 " res = pool.map(Bombe(wheel1_spec, wheel2_spec, wheel3_spec, \n",
1023 " reflector_spec, menu=menu, start_signal=start_signal, \n",
1024 " use_diagonal_board=use_diagonal_board, \n",
1025 " verify_plugboard=verify_plugboard),\n",
1027 " return [r[0] for r in res if r[1]]"
1031 "cell_type": "code",
1032 "execution_count": 36,
1043 "execution_count": 36,
1045 "output_type": "execute_result"
1049 "[r[0] for r in res if r[1]]"
1053 "cell_type": "code",
1054 "execution_count": 37,
1060 "# Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm\n",
1061 "# Enigma simulation settings are \n",
1062 "# http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJFE;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX\n",
1063 "w_enigma = Enigma(reflector_b_spec, \n",
1064 " wheel_i_spec, wheel_i_pegs,\n",
1065 " wheel_v_spec, wheel_v_pegs,\n",
1066 " wheel_iii_spec, wheel_iii_pegs,\n",
1068 " 'ua pf rq so ni ey bg hl tx zj')"
1072 "cell_type": "code",
1073 "execution_count": 38,
1084 "execution_count": 38,
1086 "output_type": "execute_result"
1090 "w_enigma.set_wheels('j', 'e', 'b')\n",
1091 "tuple(unpos(p) for p in w_enigma.wheel_positions)"
1095 "cell_type": "code",
1096 "execution_count": 39,
1107 "execution_count": 39,
1109 "output_type": "execute_result"
1113 "w_enigma.set_wheels('j', 'e', 'b')\n",
1114 "pt = 'someplaintext'\n",
1115 "ct = w_enigma.encipher(pt)\n",
1120 "cell_type": "code",
1121 "execution_count": 40,
1132 "execution_count": 40,
1134 "output_type": "execute_result"
1138 "w_enigma.wheel_positions_l"
1142 "cell_type": "code",
1143 "execution_count": 41,
1151 "[MenuIem(before='s', after='d', number=1),\n",
1152 " MenuIem(before='o', after='h', number=2),\n",
1153 " MenuIem(before='m', after='n', number=3),\n",
1154 " MenuIem(before='e', after='p', number=4),\n",
1155 " MenuIem(before='p', after='f', number=5),\n",
1156 " MenuIem(before='l', after='o', number=6),\n",
1157 " MenuIem(before='a', after='r', number=7),\n",
1158 " MenuIem(before='i', after='e', number=8),\n",
1159 " MenuIem(before='n', after='e', number=9),\n",
1160 " MenuIem(before='t', after='i', number=10),\n",
1161 " MenuIem(before='e', after='m', number=11),\n",
1162 " MenuIem(before='x', after='g', number=12),\n",
1163 " MenuIem(before='t', after='g', number=13)]"
1166 "execution_count": 41,
1168 "output_type": "execute_result"
1172 "w_menu = [MenuItem(p, c, i+1) for i, (p, c) in enumerate(zip(pt, ct))]\n",
1177 "cell_type": "code",
1178 "execution_count": 42,
1187 "[('a', 'y', 'm'),\n",
1188 " ('c', 'p', 'v'),\n",
1189 " ('c', 's', 'f'),\n",
1190 " ('c', 'w', 'j'),\n",
1191 " ('d', 'r', 'k'),\n",
1192 " ('e', 'l', 'f'),\n",
1193 " ('e', 's', 'v'),\n",
1194 " ('e', 'y', 'd'),\n",
1195 " ('e', 'y', 'o'),\n",
1196 " ('f', 'z', 'x'),\n",
1197 " ('g', 'b', 'l'),\n",
1198 " ('g', 'c', 'd'),\n",
1199 " ('g', 'c', 'f'),\n",
1200 " ('g', 'j', 'p'),\n",
1201 " ('h', 'c', 'i'),\n",
1202 " ('h', 'm', 'w'),\n",
1203 " ('h', 'o', 'd'),\n",
1204 " ('h', 'p', 'b'),\n",
1205 " ('h', 's', 't'),\n",
1206 " ('i', 'b', 's'),\n",
1207 " ('i', 'v', 'b'),\n",
1208 " ('j', 'y', 'u'),\n",
1209 " ('k', 'b', 'x'),\n",
1210 " ('k', 'f', 't'),\n",
1211 " ('k', 'l', 'e'),\n",
1212 " ('k', 'l', 'm'),\n",
1213 " ('k', 'r', 'z'),\n",
1214 " ('k', 's', 'p'),\n",
1215 " ('l', 'd', 'z'),\n",
1216 " ('l', 'i', 'y'),\n",
1217 " ('l', 'y', 'f'),\n",
1218 " ('m', 'b', 'h'),\n",
1219 " ('m', 'p', 'l'),\n",
1220 " ('n', 'l', 'r'),\n",
1221 " ('o', 'k', 'x'),\n",
1222 " ('p', 'a', 'g'),\n",
1223 " ('p', 'c', 'v'),\n",
1224 " ('p', 'f', 'o'),\n",
1225 " ('p', 'm', 'i'),\n",
1226 " ('p', 'x', 'n'),\n",
1227 " ('p', 'x', 'p'),\n",
1228 " ('q', 'q', 'n'),\n",
1229 " ('q', 'r', 'w'),\n",
1230 " ('q', 'v', 'l'),\n",
1231 " ('q', 'x', 't'),\n",
1232 " ('s', 'a', 'h'),\n",
1233 " ('s', 'h', 'v'),\n",
1234 " ('s', 'l', 'p'),\n",
1235 " ('s', 'l', 's'),\n",
1236 " ('u', 'r', 'h'),\n",
1237 " ('v', 'v', 'v'),\n",
1238 " ('v', 'x', 'a'),\n",
1239 " ('w', 'j', 'z'),\n",
1240 " ('w', 'k', 'u'),\n",
1241 " ('x', 'f', 'p'),\n",
1242 " ('x', 'j', 'n'),\n",
1243 " ('x', 'o', 'q'),\n",
1244 " ('x', 'x', 'x'),\n",
1245 " ('y', 'n', 'c'),\n",
1246 " ('y', 'r', 'f'),\n",
1247 " ('z', 't', 'y'),\n",
1251 "execution_count": 42,
1253 "output_type": "execute_result"
1257 "allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1259 "with multiprocessing.Pool() as pool:\n",
1260 " res = pool.map(Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, \n",
1261 " menu=w_menu, verify_plugboard=False),\n",
1263 "[r[0] for r in res if r[1]]"
1267 "cell_type": "code",
1268 "execution_count": 43,
1279 "execution_count": 43,
1281 "output_type": "execute_result"
1285 "len([r[0] for r in res if r[1]])"
1289 "cell_type": "code",
1290 "execution_count": 44,
1299 "[('c', 'p', 'v'),\n",
1300 " ('c', 's', 'f'),\n",
1301 " ('e', 'l', 'f'),\n",
1302 " ('g', 'c', 'f'),\n",
1303 " ('j', 'y', 'u'),\n",
1304 " ('o', 'k', 'x'),\n",
1305 " ('p', 'a', 'g'),\n",
1306 " ('q', 'q', 'n'),\n",
1307 " ('q', 'v', 'l'),\n",
1308 " ('q', 'x', 't'),\n",
1309 " ('s', 'l', 'p'),\n",
1310 " ('u', 'r', 'h'),\n",
1314 "execution_count": 44,
1316 "output_type": "execute_result"
1320 "allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1322 "with multiprocessing.Pool() as pool:\n",
1323 " res = pool.map(Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, \n",
1324 " menu=w_menu, verify_plugboard=True),\n",
1326 "[r[0] for r in res if r[1]]"
1330 "cell_type": "code",
1331 "execution_count": 45,
1339 "[('c', 'p', 'v'),\n",
1340 " ('c', 's', 'f'),\n",
1341 " ('e', 'l', 'f'),\n",
1342 " ('g', 'c', 'f'),\n",
1343 " ('j', 'y', 'u'),\n",
1344 " ('o', 'k', 'x'),\n",
1345 " ('p', 'a', 'g'),\n",
1346 " ('q', 'q', 'n'),\n",
1347 " ('q', 'v', 'l'),\n",
1348 " ('q', 'x', 't'),\n",
1349 " ('s', 'l', 'p'),\n",
1350 " ('u', 'r', 'h'),\n",
1354 "execution_count": 45,
1356 "output_type": "execute_result"
1360 "run_multi_bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, w_menu)"
1364 "cell_type": "code",
1365 "execution_count": 46,
1371 "# allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1373 "# with multiprocessing.Pool() as pool:\n",
1374 "# res = pool.map(Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, \n",
1375 "# menu=w_menu, start_signal=Signal('t', 'x')),\n",
1377 "# [r[0] for r in res if r[1]]"
1381 "cell_type": "code",
1382 "execution_count": 47,
1393 "execution_count": 47,
1395 "output_type": "execute_result"
1399 "len([r[0] for r in res if r[1]])"
1403 "cell_type": "code",
1404 "execution_count": 48,
1410 "w_bombe = Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, \n",
1415 "cell_type": "code",
1416 "execution_count": 49,
1424 "Signal(bank='e', wire='e')"
1427 "execution_count": 49,
1429 "output_type": "execute_result"
1433 "w_bombe.test_start"
1437 "cell_type": "code",
1438 "execution_count": 50,
1449 "execution_count": 50,
1451 "output_type": "execute_result"
1455 "w_bombe.test(start_positions=('e', 'l', 'f'))"
1459 "cell_type": "code",
1460 "execution_count": 51,
1471 "execution_count": 51,
1473 "output_type": "execute_result"
1477 "w_bombe.test(Signal('t', 'x'), ('e', 'l', 'f'))"
1481 "cell_type": "code",
1482 "execution_count": 52,
1489 "output_type": "stream",
1492 "a : a.cdefghi..l.nopqrst.vwx..\n",
1493 "b : ....efghi...mnop.......x..\n",
1494 "c : a....fg.i..lmn.p.r.t...x..\n",
1495 "d : a...efghij.lmn...rstu..xyz\n",
1496 "e : ab.defghijklmnopqrstuvwxyz\n",
1497 "f : abcde.ghijklmnopqrstuvwxyz\n",
1498 "g : abcdef.hijklmnopqrstuvwxyz\n",
1499 "h : ab.defghi...mnopq.stuvwx..\n",
1500 "i : abcdefgh.jklmnopqrstuvwxyz\n",
1501 "j : ...defg.i...mn.p...t...x..\n",
1502 "k : ....efg.i..lmnop.r.t...x..\n",
1503 "l : a.cdefg.i.k.mnopqr.t..wxyz\n",
1504 "m : .bcdefghijklmnopqrstuvwxyz\n",
1505 "n : abcdefghijklmnopqr.tuvwxyz\n",
1506 "o : ab..efghi.klmnopqr.t...xyz\n",
1507 "p : abc.efghijklmnopqrstuvwxyz\n",
1508 "q : a...efghi..lmnop.r.t...x..\n",
1509 "r : a.cdefg.i.klmnopqrst..w..z\n",
1510 "s : a..defghi...m..p.rstuv.xyz\n",
1511 "t : a.cdefghijklmnopqrstuvwxyz\n",
1512 "u : ...defghi...mn.p..st...x..\n",
1513 "v : a...efghi...mn.p..st...x..\n",
1514 "w : a...efghi..lmn.p.r.t...x..\n",
1515 "x : abcdefghijklmnopq.stuvwxyz\n",
1516 "y : ...defg.i..lmnop..st...x..\n",
1517 "z : ...defg.i..lmnop.rst...x..\n"
1522 "r = w_bombe.test(start_positions=('c', 'p', 'v'))\n",
1524 "for b in sorted(w_bombe.banks):\n",
1525 " print(b, ': ', end='')\n",
1526 " for w in sorted(w_bombe.banks[b]):\n",
1527 " if w_bombe.banks[b][w]:\n",
1528 " print(w, end='')\n",
1530 " print('.', end='')\n",
1535 "cell_type": "code",
1536 "execution_count": 53,
1543 "output_type": "stream",
1546 "a : abcdefghi..lmnop.rst.v.x.z\n",
1547 "b : a...ef.hi..lmnop.r.t...x..\n",
1548 "c : a..defg.i..lmn.p.rst...x..\n",
1549 "d : a.c.efghi.klmnopqrstu.wxyz\n",
1550 "e : abcdefghijklmnopqrstuvwx.z\n",
1551 "f : abcdefghijklmno.qrstuvwxyz\n",
1552 "g : a.cdefghijklmnopqrstuvwxyz\n",
1553 "h : ab.defghi...mnopqrstuvwxyz\n",
1554 "i : abcdefghijklm.opqrstuvwxyz\n",
1555 "j : ....efg.i..lmnop...t...x..\n",
1556 "k : ...defg.i..lmn.p..st...x..\n",
1557 "l : abcdefg.ijklmnopqrstuv.x..\n",
1558 "m : abcdefghijkl.nopqrstuvwxyz\n",
1559 "n : abcdefgh.jklmnopqrstuvwxyz\n",
1560 "o : ab.defghij.lmnop.r.tuvwxyz\n",
1561 "p : abcde.ghijklmnopqrstuvwxyz\n",
1562 "q : ...defghi..lmn.p..st...x..\n",
1563 "r : abcdefghi..lmnop.rst.v.x.z\n",
1564 "s : a.cdefghi.klmn.pqr.tuvwxyz\n",
1565 "t : abcdefghijklmnopqrstuvw.yz\n",
1566 "u : ...defghi..lmnop..st...x..\n",
1567 "v : a...efghi..lmnop.rst...x..\n",
1568 "w : ...defghi...mnop..st...x..\n",
1569 "x : abcdefghijklmnopqrs.uvwxyz\n",
1570 "y : ...d.fghi...mnop..st...x..\n",
1571 "z : a..defghi...mnop.rst...x..\n"
1576 "r = w_bombe.test(start_positions=('e', 'l', 'f'))\n",
1578 "for b in sorted(w_bombe.banks):\n",
1579 " print(b, ': ', end='')\n",
1580 " for w in sorted(w_bombe.banks[b]):\n",
1581 " if w_bombe.banks[b][w]:\n",
1582 " print(w, end='')\n",
1584 " print('.', end='')\n",
1589 "cell_type": "code",
1590 "execution_count": 54,
1598 "{frozenset({'m'}),\n",
1599 " frozenset({'i', 'n'}),\n",
1600 " frozenset({'f', 'p'}),\n",
1601 " frozenset({'t', 'x'}),\n",
1602 " frozenset({'e', 'y'}),\n",
1603 " frozenset({'b', 'g'})}"
1606 "execution_count": 54,
1608 "output_type": "execute_result"
1612 "ps = w_bombe.possible_plugboards()\n",
1617 "cell_type": "code",
1618 "execution_count": 55,
1629 "execution_count": 55,
1631 "output_type": "execute_result"
1635 "all(s0.isdisjoint(s1) for s0 in ps for s1 in ps if s0 != s1)"
1639 "cell_type": "code",
1640 "execution_count": 56,
1648 "({frozenset({1, 2}), frozenset({3, 4}), frozenset({2, 3})},\n",
1649 " frozenset({1, 2}),\n",
1650 " frozenset({3, 4}),\n",
1651 " frozenset({2, 3}))"
1654 "execution_count": 56,
1656 "output_type": "execute_result"
1661 "f1 = frozenset((1, 2))\n",
1662 "f2 = frozenset((3, 4))\n",
1663 "f3 = frozenset((2, 3))\n",
1664 "s = s.union({f1})\n",
1665 "s = s.union({f2})\n",
1666 "s = s.union({f1})\n",
1667 "s = s.union({f3})\n",
1672 "cell_type": "code",
1673 "execution_count": 57,
1684 "execution_count": 57,
1686 "output_type": "execute_result"
1690 "all(s0.isdisjoint(s1) for s0 in s for s1 in s if s0 != s1)"
1694 "cell_type": "code",
1695 "execution_count": 58,
1706 "execution_count": 58,
1708 "output_type": "execute_result"
1712 "{1, 2}.isdisjoint({1, 6})"
1716 "cell_type": "code",
1717 "execution_count": null,
1727 "display_name": "Python 3",
1728 "language": "python",
1732 "codemirror_mode": {
1736 "file_extension": ".py",
1737 "mimetype": "text/x-python",
1739 "nbconvert_exporter": "python",
1740 "pygments_lexer": "ipython3",