Updated for challenge 9
[cipher-tools.git] / bombe.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": true
8 },
9 "outputs": [],
10 "source": [
11 "import string\n",
12 "import collections\n",
13 "import multiprocessing\n",
14 "import itertools\n",
15 "from enigma import *"
16 ]
17 },
18 {
19 "cell_type": "code",
20 "execution_count": 2,
21 "metadata": {
22 "collapsed": true
23 },
24 "outputs": [],
25 "source": [
26 "Signal = collections.namedtuple('Signal', ['bank', 'wire'])\n",
27 "Connection = collections.namedtuple('Connection', ['banks', 'scrambler'])\n",
28 "MenuItem = collections.namedtuple('MenuIem', ['before', 'after', 'number'])"
29 ]
30 },
31 {
32 "cell_type": "code",
33 "execution_count": 3,
34 "metadata": {
35 "collapsed": true
36 },
37 "outputs": [],
38 "source": [
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",
46 " \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",
52 " else:\n",
53 " return object.__getattribute__(self, name)\n",
54 " \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",
59 " \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",
68 " return g\n",
69 " \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) "
74 ]
75 },
76 {
77 "cell_type": "code",
78 "execution_count": 4,
79 "metadata": {
80 "collapsed": true
81 },
82 "outputs": [],
83 "source": [
84 "class Bombe(object):\n",
85 " \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",
94 " if menu:\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",
100 " \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",
106 " else:\n",
107 " return object.__getattribute__(self, name)\n",
108 " \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",
114 " \n",
115 " def add_connection(self, bank_before, bank_after, scrambler):\n",
116 " self.connections += [Connection([bank_before, bank_after], scrambler)]\n",
117 " \n",
118 " def read_menu(self, menu):\n",
119 " self.connections = []\n",
120 " for item in menu:\n",
121 " scrambler = Scrambler(self.wheel1_spec, self.wheel2_spec, self.wheel3_spec,\n",
122 " self.reflector_spec,\n",
123 " wheel3_pos=unpos(item.number - 1))\n",
124 " self.add_connection(item.before, item.after, scrambler)\n",
125 " most_common_letter = (collections.Counter(m.before for m in menu) + \\\n",
126 " collections.Counter(m.after for m in menu)).most_common(1)[0][0]\n",
127 " self.test_start = Signal(most_common_letter, most_common_letter)\n",
128 " \n",
129 " def set_positions(self, wheel1_pos, wheel2_pos, wheel3_pos):\n",
130 " for i, c in enumerate(self.connections):\n",
131 " c.scrambler.set_positions(wheel1_pos, wheel2_pos, unpos(pos(wheel3_pos) + i))\n",
132 " \n",
133 " def test(self, initial_signal=None, start_positions=None, use_diagonal_board=True,\n",
134 " verify_plugboard=True):\n",
135 " self.banks = {label: \n",
136 " dict(zip(string.ascii_lowercase, [False]*len(string.ascii_lowercase)))\n",
137 " for label in string.ascii_lowercase}\n",
138 " if start_positions:\n",
139 " self.set_positions(*start_positions)\n",
140 " if not initial_signal:\n",
141 " initial_signal = self.test_start\n",
142 " self.pending = [initial_signal]\n",
143 " self.propagate(use_diagonal_board)\n",
144 " live_wire_count = len([self.banks[self.test_start.bank][w] \n",
145 " for w in self.banks[self.test_start.bank] \n",
146 " if self.banks[self.test_start.bank][w]])\n",
147 " if live_wire_count < 26:\n",
148 " if verify_plugboard:\n",
149 " possibles = self.possible_plugboards()\n",
150 " return all(s0.isdisjoint(s1) for s0 in possibles for s1 in possibles if s0 != s1)\n",
151 " else:\n",
152 " return True\n",
153 " else:\n",
154 " return False\n",
155 " \n",
156 " def propagate(self, use_diagonal_board):\n",
157 " while self.pending:\n",
158 " current = self.pending[0]\n",
159 " # print(\"processing\", current)\n",
160 " self.pending = self.pending[1:]\n",
161 " if not self.banks[current.bank][current.wire]:\n",
162 " self.banks[current.bank][current.wire] = True\n",
163 " if use_diagonal_board:\n",
164 " self.pending += [Signal(current.wire, current.bank)]\n",
165 " for c in self.connections:\n",
166 " if current.bank in c.banks:\n",
167 " if len(set(c.banks)) == 1:\n",
168 " other_bank = c.banks[0]\n",
169 " else:\n",
170 " other_bank = [b for b in c.banks if b != current.bank][0]\n",
171 " other_wire = c.scrambler.lookup(current.wire)\n",
172 " # print(\" adding\", other_bank, other_wire, \"because\", c.banks)\n",
173 " self.pending += [Signal(other_bank, other_wire)]\n",
174 " \n",
175 " def run(self, run_start=None, wheel1_pos='a', wheel2_pos='a', wheel3_pos='a', use_diagonal_board=True):\n",
176 " if not run_start:\n",
177 " run_start = self.test_start\n",
178 " self.solutions = []\n",
179 " self.set_positions(wheel1_pos, wheel2_pos, wheel3_pos)\n",
180 " for run_index in range(26*26*26):\n",
181 " if self.test(initial_signal=run_start, use_diagonal_board=use_diagonal_board):\n",
182 " self.solutions += [self.connections[0].scrambler.wheel_positions_l]\n",
183 " advance3 = True\n",
184 " advance2 = False\n",
185 " advance1 = False\n",
186 " if (run_index + 1) % 26 == 0: advance2 = True\n",
187 " if (run_index + 1) % (26*26) == 0: advance1 = True\n",
188 " for c in self.connections:\n",
189 " c.scrambler.advance(advance1, advance2, advance3)\n",
190 " return self.solutions\n",
191 " \n",
192 " def possible_plugboards(self):\n",
193 " possibles = set()\n",
194 " for b in self.banks:\n",
195 " active = [w for w in self.banks[b] if self.banks[b][w]]\n",
196 " inactive = [w for w in self.banks[b] if not self.banks[b][w]]\n",
197 " if len(active) == 1:\n",
198 " possibles = possibles.union({frozenset((b, active[0]))})\n",
199 " if len(inactive) == 1:\n",
200 " possibles = possibles.union({frozenset((b, inactive[0]))})\n",
201 " return possibles\n"
202 ]
203 },
204 {
205 "cell_type": "code",
206 "execution_count": 5,
207 "metadata": {
208 "collapsed": true
209 },
210 "outputs": [],
211 "source": [
212 "bombe = Bombe(wheel_i_spec, wheel_ii_spec, wheel_iii_spec, reflector_b_spec)\n",
213 "# len(bombe.banks), bombe.banks['a'] == bombe.banks['b']"
214 ]
215 },
216 {
217 "cell_type": "code",
218 "execution_count": 6,
219 "metadata": {
220 "collapsed": true
221 },
222 "outputs": [],
223 "source": [
224 "test_enigma = Enigma(reflector_b_spec, \n",
225 " wheel_i_spec, wheel_i_pegs,\n",
226 " wheel_ii_spec, wheel_ii_pegs,\n",
227 " wheel_iii_spec, wheel_iii_pegs,\n",
228 " 1, 1, 1,\n",
229 " '')"
230 ]
231 },
232 {
233 "cell_type": "code",
234 "execution_count": 7,
235 "metadata": {},
236 "outputs": [
237 {
238 "data": {
239 "text/plain": [
240 "'opgndxcrwomnlnecjz'"
241 ]
242 },
243 "execution_count": 7,
244 "metadata": {},
245 "output_type": "execute_result"
246 }
247 ],
248 "source": [
249 "test_enigma.set_wheels('a', 'a', 'a')\n",
250 "pt = 'thisisatestmessage'\n",
251 "ct = test_enigma.encipher(pt)\n",
252 "ct"
253 ]
254 },
255 {
256 "cell_type": "code",
257 "execution_count": 8,
258 "metadata": {},
259 "outputs": [
260 {
261 "data": {
262 "text/plain": [
263 "'aas'"
264 ]
265 },
266 "execution_count": 8,
267 "metadata": {},
268 "output_type": "execute_result"
269 }
270 ],
271 "source": [
272 "cat(test_enigma.wheel_positions_l)"
273 ]
274 },
275 {
276 "cell_type": "code",
277 "execution_count": 9,
278 "metadata": {},
279 "outputs": [
280 {
281 "data": {
282 "text/plain": [
283 "[MenuIem(before='t', after='o', number=1),\n",
284 " MenuIem(before='h', after='p', number=2),\n",
285 " MenuIem(before='i', after='g', number=3),\n",
286 " MenuIem(before='s', after='n', number=4),\n",
287 " MenuIem(before='i', after='d', number=5),\n",
288 " MenuIem(before='s', after='x', number=6),\n",
289 " MenuIem(before='a', after='c', number=7),\n",
290 " MenuIem(before='t', after='r', number=8),\n",
291 " MenuIem(before='e', after='w', number=9),\n",
292 " MenuIem(before='s', after='o', number=10),\n",
293 " MenuIem(before='t', after='m', number=11),\n",
294 " MenuIem(before='m', after='n', number=12),\n",
295 " MenuIem(before='e', after='l', number=13),\n",
296 " MenuIem(before='s', after='n', number=14),\n",
297 " MenuIem(before='s', after='e', number=15),\n",
298 " MenuIem(before='a', after='c', number=16),\n",
299 " MenuIem(before='g', after='j', number=17),\n",
300 " MenuIem(before='e', after='z', number=18)]"
301 ]
302 },
303 "execution_count": 9,
304 "metadata": {},
305 "output_type": "execute_result"
306 }
307 ],
308 "source": [
309 "menu = [MenuItem(p, c, i+1) for i, (p, c) in enumerate(zip(pt, ct))]\n",
310 "menu"
311 ]
312 },
313 {
314 "cell_type": "code",
315 "execution_count": 10,
316 "metadata": {
317 "collapsed": true
318 },
319 "outputs": [],
320 "source": [
321 "def make_menu(plaintext, ciphertext):\n",
322 " return [MenuItem(p, c, i+1) \n",
323 " for i, (p, c) in enumerate(zip(plaintext, ciphertext))]"
324 ]
325 },
326 {
327 "cell_type": "code",
328 "execution_count": 11,
329 "metadata": {},
330 "outputs": [
331 {
332 "data": {
333 "text/plain": [
334 "[MenuIem(before='t', after='o', number=1),\n",
335 " MenuIem(before='h', after='p', number=2),\n",
336 " MenuIem(before='i', after='g', number=3),\n",
337 " MenuIem(before='s', after='n', number=4),\n",
338 " MenuIem(before='i', after='d', number=5),\n",
339 " MenuIem(before='s', after='x', number=6),\n",
340 " MenuIem(before='a', after='c', number=7),\n",
341 " MenuIem(before='t', after='r', number=8),\n",
342 " MenuIem(before='e', after='w', number=9),\n",
343 " MenuIem(before='s', after='o', number=10),\n",
344 " MenuIem(before='t', after='m', number=11),\n",
345 " MenuIem(before='m', after='n', number=12),\n",
346 " MenuIem(before='e', after='l', number=13),\n",
347 " MenuIem(before='s', after='n', number=14),\n",
348 " MenuIem(before='s', after='e', number=15),\n",
349 " MenuIem(before='a', after='c', number=16),\n",
350 " MenuIem(before='g', after='j', number=17),\n",
351 " MenuIem(before='e', after='z', number=18)]"
352 ]
353 },
354 "execution_count": 11,
355 "metadata": {},
356 "output_type": "execute_result"
357 }
358 ],
359 "source": [
360 "make_menu(pt, ct)"
361 ]
362 },
363 {
364 "cell_type": "code",
365 "execution_count": 12,
366 "metadata": {},
367 "outputs": [
368 {
369 "data": {
370 "text/plain": [
371 "'s'"
372 ]
373 },
374 "execution_count": 12,
375 "metadata": {},
376 "output_type": "execute_result"
377 }
378 ],
379 "source": [
380 "(collections.Counter(m.before for m in menu) + collections.Counter(m.after for m in menu)).most_common(1)[0][0]"
381 ]
382 },
383 {
384 "cell_type": "code",
385 "execution_count": 13,
386 "metadata": {
387 "collapsed": true
388 },
389 "outputs": [],
390 "source": [
391 "bombe.read_menu(menu)"
392 ]
393 },
394 {
395 "cell_type": "code",
396 "execution_count": 14,
397 "metadata": {},
398 "outputs": [
399 {
400 "data": {
401 "text/plain": [
402 "18"
403 ]
404 },
405 "execution_count": 14,
406 "metadata": {},
407 "output_type": "execute_result"
408 }
409 ],
410 "source": [
411 "len(bombe.connections)"
412 ]
413 },
414 {
415 "cell_type": "code",
416 "execution_count": 15,
417 "metadata": {},
418 "outputs": [
419 {
420 "name": "stdout",
421 "output_type": "stream",
422 "text": [
423 "['t', 'o'] aaa\n",
424 "['h', 'p'] aab\n",
425 "['i', 'g'] aac\n",
426 "['s', 'n'] aad\n",
427 "['i', 'd'] aae\n",
428 "['s', 'x'] aaf\n",
429 "['a', 'c'] aag\n",
430 "['t', 'r'] aah\n",
431 "['e', 'w'] aai\n",
432 "['s', 'o'] aaj\n",
433 "['t', 'm'] aak\n",
434 "['m', 'n'] aal\n",
435 "['e', 'l'] aam\n",
436 "['s', 'n'] aan\n",
437 "['s', 'e'] aao\n",
438 "['a', 'c'] aap\n",
439 "['g', 'j'] aaq\n",
440 "['e', 'z'] aar\n"
441 ]
442 }
443 ],
444 "source": [
445 "for c in bombe.connections:\n",
446 " print(c.banks, cat(c.scrambler.wheel_positions_l))"
447 ]
448 },
449 {
450 "cell_type": "code",
451 "execution_count": 16,
452 "metadata": {},
453 "outputs": [
454 {
455 "data": {
456 "text/plain": [
457 "'ot:hp:gi:ns:di:sx:ac:rt:ew:os:mt:mn:el:ns:es:ac:gj:ez'"
458 ]
459 },
460 "execution_count": 16,
461 "metadata": {},
462 "output_type": "execute_result"
463 }
464 ],
465 "source": [
466 "':'.join(cat(sorted(c.banks)) for c in bombe.connections)"
467 ]
468 },
469 {
470 "cell_type": "code",
471 "execution_count": 17,
472 "metadata": {},
473 "outputs": [
474 {
475 "data": {
476 "text/plain": [
477 "'aaa:aab:aac:aad:aae:aaf:aag:aah:aai:aaj:aak:aal:aam:aan:aao:aap:aaq:aar'"
478 ]
479 },
480 "execution_count": 17,
481 "metadata": {},
482 "output_type": "execute_result"
483 }
484 ],
485 "source": [
486 "':'.join(cat(c.scrambler.wheel_positions_l) for c in bombe.connections)"
487 ]
488 },
489 {
490 "cell_type": "code",
491 "execution_count": 18,
492 "metadata": {},
493 "outputs": [
494 {
495 "data": {
496 "text/plain": [
497 "False"
498 ]
499 },
500 "execution_count": 18,
501 "metadata": {},
502 "output_type": "execute_result"
503 }
504 ],
505 "source": [
506 "bombe.test(Signal('t', 't'))"
507 ]
508 },
509 {
510 "cell_type": "code",
511 "execution_count": 19,
512 "metadata": {},
513 "outputs": [
514 {
515 "data": {
516 "text/plain": [
517 "{'a': True,\n",
518 " 'b': True,\n",
519 " 'c': True,\n",
520 " 'd': True,\n",
521 " 'e': True,\n",
522 " 'f': True,\n",
523 " 'g': True,\n",
524 " 'h': True,\n",
525 " 'i': True,\n",
526 " 'j': True,\n",
527 " 'k': True,\n",
528 " 'l': True,\n",
529 " 'm': True,\n",
530 " 'n': True,\n",
531 " 'o': True,\n",
532 " 'p': True,\n",
533 " 'q': True,\n",
534 " 'r': True,\n",
535 " 's': True,\n",
536 " 't': True,\n",
537 " 'u': True,\n",
538 " 'v': True,\n",
539 " 'w': True,\n",
540 " 'x': True,\n",
541 " 'y': True,\n",
542 " 'z': True}"
543 ]
544 },
545 "execution_count": 19,
546 "metadata": {},
547 "output_type": "execute_result"
548 }
549 ],
550 "source": [
551 "bombe.banks['t']"
552 ]
553 },
554 {
555 "cell_type": "code",
556 "execution_count": 20,
557 "metadata": {},
558 "outputs": [
559 {
560 "name": "stdout",
561 "output_type": "stream",
562 "text": [
563 "a : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
564 "b : AbCDEfGHIJkLMNOPqRSTuvWXyZ\n",
565 "c : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
566 "d : ABCDEFGHIJKLMNOPQRSTUVWXyZ\n",
567 "e : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
568 "f : AbCDEfGHIJkLMNOPqRSTuvWXyZ\n",
569 "g : ABCDEFGHIJKLMNOPQRSTuVWXYZ\n",
570 "h : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
571 "i : ABCDEFGHIJKLMNOPQRSTUvWXYZ\n",
572 "j : ABCDEFGHIjKLMNOPQRSTUVWXYZ\n",
573 "k : AbCDEfGHIJkLMNOPqRSTuvWXyZ\n",
574 "l : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
575 "m : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
576 "n : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
577 "o : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
578 "p : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
579 "q : AbCDEfGHIJkLMNOPqRSTuvWXyZ\n",
580 "r : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
581 "s : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
582 "t : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
583 "u : AbCDEfgHIJkLMNOPqRSTuvWXyZ\n",
584 "v : AbCDEfGHiJkLMNOPqRSTuvWXyZ\n",
585 "w : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
586 "x : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
587 "y : AbCdEfGHIJkLMNOPqRSTuvWXyZ\n",
588 "z : ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
589 ]
590 }
591 ],
592 "source": [
593 "for b in sorted(bombe.banks):\n",
594 " print(b, ': ', end='')\n",
595 " for w in sorted(bombe.banks[b]):\n",
596 " if bombe.banks[b][w]:\n",
597 " print(w.upper(), end='')\n",
598 " else:\n",
599 " print(w, end='')\n",
600 " print('')"
601 ]
602 },
603 {
604 "cell_type": "code",
605 "execution_count": 21,
606 "metadata": {},
607 "outputs": [
608 {
609 "name": "stdout",
610 "output_type": "stream",
611 "text": [
612 "a : abcdefghijklmnopqrstuvwxyz\n",
613 "b : a.cde.ghij.lmnop.rst..wx.z\n",
614 "c : abcdefghijklmnopqrstuvwxyz\n",
615 "d : abcdefghijklmnopqrstuvwx.z\n",
616 "e : abcdefghijklmnopqrstuvwxyz\n",
617 "f : a.cde.ghij.lmnop.rst..wx.z\n",
618 "g : abcdefghijklmnopqrst.vwxyz\n",
619 "h : abcdefghijklmnopqrstuvwxyz\n",
620 "i : abcdefghijklmnopqrstu.wxyz\n",
621 "j : abcdefghi.klmnopqrstuvwxyz\n",
622 "k : a.cde.ghij.lmnop.rst..wx.z\n",
623 "l : abcdefghijklmnopqrstuvwxyz\n",
624 "m : abcdefghijklmnopqrstuvwxyz\n",
625 "n : abcdefghijklmnopqrstuvwxyz\n",
626 "o : abcdefghijklmnopqrstuvwxyz\n",
627 "p : abcdefghijklmnopqrstuvwxyz\n",
628 "q : a.cde.ghij.lmnop.rst..wx.z\n",
629 "r : abcdefghijklmnopqrstuvwxyz\n",
630 "s : abcdefghijklmnopqrstuvwxyz\n",
631 "t : abcdefghijklmnopqrstuvwxyz\n",
632 "u : a.cde..hij.lmnop.rst..wx.z\n",
633 "v : a.cde.gh.j.lmnop.rst..wx.z\n",
634 "w : abcdefghijklmnopqrstuvwxyz\n",
635 "x : abcdefghijklmnopqrstuvwxyz\n",
636 "y : a.c.e.ghij.lmnop.rst..wx.z\n",
637 "z : abcdefghijklmnopqrstuvwxyz\n"
638 ]
639 }
640 ],
641 "source": [
642 "for b in sorted(bombe.banks):\n",
643 " print(b, ': ', end='')\n",
644 " for w in sorted(bombe.banks[b]):\n",
645 " if bombe.banks[b][w]:\n",
646 " print(w, end='')\n",
647 " else:\n",
648 " print('.', end='')\n",
649 " print('')"
650 ]
651 },
652 {
653 "cell_type": "code",
654 "execution_count": 22,
655 "metadata": {},
656 "outputs": [
657 {
658 "data": {
659 "text/plain": [
660 "('a', 'a', 'a')"
661 ]
662 },
663 "execution_count": 22,
664 "metadata": {},
665 "output_type": "execute_result"
666 }
667 ],
668 "source": [
669 "bombe.wheel_positions_l"
670 ]
671 },
672 {
673 "cell_type": "code",
674 "execution_count": 23,
675 "metadata": {},
676 "outputs": [
677 {
678 "name": "stdout",
679 "output_type": "stream",
680 "text": [
681 "['t', 'o'] pqr\n",
682 "['h', 'p'] pqs\n",
683 "['i', 'g'] pqt\n",
684 "['s', 'n'] pqu\n",
685 "['i', 'd'] pqv\n",
686 "['s', 'x'] pqw\n",
687 "['a', 'c'] pqx\n",
688 "['t', 'r'] pqy\n",
689 "['e', 'w'] pqz\n",
690 "['s', 'o'] pqa\n",
691 "['t', 'm'] pqb\n",
692 "['m', 'n'] pqc\n",
693 "['e', 'l'] pqd\n",
694 "['s', 'n'] pqe\n",
695 "['s', 'e'] pqf\n",
696 "['a', 'c'] pqg\n",
697 "['g', 'j'] pqh\n",
698 "['e', 'z'] pqi\n"
699 ]
700 }
701 ],
702 "source": [
703 "bombe.set_positions('p', 'q', 'r')\n",
704 "for c in bombe.connections:\n",
705 " print(c.banks, cat(c.scrambler.wheel_positions_l))"
706 ]
707 },
708 {
709 "cell_type": "code",
710 "execution_count": 24,
711 "metadata": {
712 "collapsed": true
713 },
714 "outputs": [],
715 "source": [
716 "# bombe.run()\n",
717 "# print('x')"
718 ]
719 },
720 {
721 "cell_type": "code",
722 "execution_count": 25,
723 "metadata": {},
724 "outputs": [
725 {
726 "name": "stdout",
727 "output_type": "stream",
728 "text": [
729 "a : .b.defghijklmnopqrstuvwxyz\n",
730 "b : a.cde.ghij.lmnop.rst..wx.z\n",
731 "c : .b.defghijklmnopqrstuvwxyz\n",
732 "d : abc.e.gh.jklmnopqrstuvwxyz\n",
733 "e : abcd.fghijklmnopqrstuvwxyz\n",
734 "f : a.c.e.g.ij.lmno..rst..wx.z\n",
735 "g : abcdef.h..klmnopqrstuvwxyz\n",
736 "h : abcde.g.ij.lmno.qrst..wxyz\n",
737 "i : abc.ef.h.jklmnopqrstuvwxyz\n",
738 "j : abcdef.hi.klmnopqrstuvwx.z\n",
739 "k : a.cde.g.ij.lmno..rst..wx.z\n",
740 "l : abcdefghijk.mnopqrstuvwxyz\n",
741 "m : abcdefghijkl.nopqrstuvwxyz\n",
742 "n : abcdefghijklm.opqrstuvwxyz\n",
743 "o : abcdefghijklmn.pqrstuvwxyz\n",
744 "p : abcde.g.ij.lmno.qrst..wxyz\n",
745 "q : a.cde.ghij.lmnop.rst..wx.z\n",
746 "r : abcdefghijklmnopq.stuvwxyz\n",
747 "s : abcdefghijklmnopqr.tuvwxyz\n",
748 "t : abcdefghijklmnopqrs.uvwxyz\n",
749 "u : a.cde.g.ij.lmno..rst..wx.z\n",
750 "v : a.cde.g.ij.lmno..rst..wx.z\n",
751 "w : abcdefghijklmnopqrstuv.xyz\n",
752 "x : abcdefghijklmnopqrstuvw.yz\n",
753 "y : a.cde.ghi..lmnop.rst..wx.z\n",
754 "z : abcdefghijklmnopqrstuvwxy.\n"
755 ]
756 }
757 ],
758 "source": [
759 "bombe.set_positions('a', 'a', 'b')\n",
760 "bombe.test(Signal('s', 'a'))\n",
761 "\n",
762 "for b in sorted(bombe.banks):\n",
763 " print(b, ': ', end='')\n",
764 " for w in sorted(bombe.banks[b]):\n",
765 " if bombe.banks[b][w]:\n",
766 " print(w, end='')\n",
767 " else:\n",
768 " print('.', end='')\n",
769 " print('')"
770 ]
771 },
772 {
773 "cell_type": "code",
774 "execution_count": 26,
775 "metadata": {},
776 "outputs": [
777 {
778 "name": "stdout",
779 "output_type": "stream",
780 "text": [
781 "a : ..........................\n",
782 "b : ..........................\n",
783 "c : ..........................\n",
784 "d : ..........................\n",
785 "e : ....e.....................\n",
786 "f : ..........................\n",
787 "g : ..........................\n",
788 "h : ..........................\n",
789 "i : ..........................\n",
790 "j : ..........................\n",
791 "k : ..........................\n",
792 "l : ...........l..............\n",
793 "m : ............m.............\n",
794 "n : .............n............\n",
795 "o : ..............o...........\n",
796 "p : ..........................\n",
797 "q : ..........................\n",
798 "r : .................r........\n",
799 "s : ..................s.......\n",
800 "t : ...................t......\n",
801 "u : ..........................\n",
802 "v : ..........................\n",
803 "w : ......................w...\n",
804 "x : .......................x..\n",
805 "y : ..........................\n",
806 "z : .........................z\n"
807 ]
808 }
809 ],
810 "source": [
811 "bombe.set_positions('a', 'a', 'b')\n",
812 "bombe.test()\n",
813 "\n",
814 "for b in sorted(bombe.banks):\n",
815 " print(b, ': ', end='')\n",
816 " for w in sorted(bombe.banks[b]):\n",
817 " if bombe.banks[b][w]:\n",
818 " print(w, end='')\n",
819 " else:\n",
820 " print('.', end='')\n",
821 " print('')"
822 ]
823 },
824 {
825 "cell_type": "code",
826 "execution_count": 27,
827 "metadata": {},
828 "outputs": [
829 {
830 "data": {
831 "text/plain": [
832 "1"
833 ]
834 },
835 "execution_count": 27,
836 "metadata": {},
837 "output_type": "execute_result"
838 }
839 ],
840 "source": [
841 "len([bombe.banks['t'][w] for w in bombe.banks['t'] if bombe.banks['t'][w]])"
842 ]
843 },
844 {
845 "cell_type": "code",
846 "execution_count": 28,
847 "metadata": {
848 "collapsed": true
849 },
850 "outputs": [],
851 "source": [
852 "# %%timeit\n",
853 "# results = bombe.run()\n",
854 "# print(len(results), ('a', 'a', 'b') in results)"
855 ]
856 },
857 {
858 "cell_type": "code",
859 "execution_count": 29,
860 "metadata": {
861 "collapsed": true
862 },
863 "outputs": [],
864 "source": [
865 "# %%timeit\n",
866 "# results = bombe.run(use_diagonal_board=False)\n",
867 "# print(len(results), ('a', 'a', 'b') in results)"
868 ]
869 },
870 {
871 "cell_type": "code",
872 "execution_count": 30,
873 "metadata": {},
874 "outputs": [
875 {
876 "data": {
877 "text/plain": [
878 "('a', 'a', 'b')"
879 ]
880 },
881 "execution_count": 30,
882 "metadata": {},
883 "output_type": "execute_result"
884 }
885 ],
886 "source": [
887 "bombe.wheel_positions_l"
888 ]
889 },
890 {
891 "cell_type": "code",
892 "execution_count": 31,
893 "metadata": {},
894 "outputs": [
895 {
896 "data": {
897 "text/plain": [
898 "False"
899 ]
900 },
901 "execution_count": 31,
902 "metadata": {},
903 "output_type": "execute_result"
904 }
905 ],
906 "source": [
907 "bombe.test(Signal('t', 't'), ('p', 'p', 'p'))"
908 ]
909 },
910 {
911 "cell_type": "code",
912 "execution_count": 32,
913 "metadata": {},
914 "outputs": [
915 {
916 "data": {
917 "text/plain": [
918 "('p', 'p', 'p')"
919 ]
920 },
921 "execution_count": 32,
922 "metadata": {},
923 "output_type": "execute_result"
924 }
925 ],
926 "source": [
927 "bombe.wheel_positions_l"
928 ]
929 },
930 {
931 "cell_type": "code",
932 "execution_count": 33,
933 "metadata": {},
934 "outputs": [
935 {
936 "name": "stdout",
937 "output_type": "stream",
938 "text": [
939 "a : abcdefghijklmnop.rst.vwxyz\n",
940 "b : a.cde.g.ij.lmno..rst..wx.z\n",
941 "c : abcdefghijklmnop.rst.vwxyz\n",
942 "d : abcdefghijklmnopqrstuvwxyz\n",
943 "e : abcdefghijklmnopqrstuvwxyz\n",
944 "f : a.cde.g.ij.lmno..rst..wx.z\n",
945 "g : abcdefghijklmnopqrstuvwxyz\n",
946 "h : a.cde.ghijklmnop.rst.vwxyz\n",
947 "i : abcdefghijklmnopqrstuvwxyz\n",
948 "j : abcdefghijklmnopqrstuvwxyz\n",
949 "k : a.cde.ghij.lmnop.rst..wx.z\n",
950 "l : abcdefghijklmnopqrstuvwxyz\n",
951 "m : abcdefghijklmnopqrstuvwxyz\n",
952 "n : abcdefghijklmnopqrstuvwxyz\n",
953 "o : abcdefghijklmnopqrstuvwxyz\n",
954 "p : a.cde.ghijklmnop.rst.vwxyz\n",
955 "q : ...de.g.ij.lmno..rst..wx.z\n",
956 "r : abcdefghijklmnopqrstuvwxyz\n",
957 "s : abcdefghijklmnopqrstuvwxyz\n",
958 "t : abcdefghijklmnopqrstuvwxyz\n",
959 "u : ...de.g.ij.lmno..rst..wx.z\n",
960 "v : a.cde.ghij.lmnop.rst..wx.z\n",
961 "w : abcdefghijklmnopqrstuvwxyz\n",
962 "x : abcdefghijklmnopqrstuvwxyz\n",
963 "y : a.cde.ghij.lmnop.rst..wx.z\n",
964 "z : abcdefghijklmnopqrstuvwxyz\n"
965 ]
966 }
967 ],
968 "source": [
969 "for b in sorted(bombe.banks):\n",
970 " print(b, ': ', end='')\n",
971 " for w in sorted(bombe.banks[b]):\n",
972 " if bombe.banks[b][w]:\n",
973 " print(w, end='')\n",
974 " else:\n",
975 " print('.', end='')\n",
976 " print('')"
977 ]
978 },
979 {
980 "cell_type": "code",
981 "execution_count": 34,
982 "metadata": {},
983 "outputs": [
984 {
985 "data": {
986 "text/plain": [
987 "17576"
988 ]
989 },
990 "execution_count": 34,
991 "metadata": {},
992 "output_type": "execute_result"
993 }
994 ],
995 "source": [
996 "allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
997 "len(list(allwheels))"
998 ]
999 },
1000 {
1001 "cell_type": "code",
1002 "execution_count": 35,
1003 "metadata": {},
1004 "outputs": [
1005 {
1006 "data": {
1007 "text/plain": [
1008 "(('a', 'a', 'b'), True)"
1009 ]
1010 },
1011 "execution_count": 35,
1012 "metadata": {},
1013 "output_type": "execute_result"
1014 }
1015 ],
1016 "source": [
1017 "b = Bombe(wheel_i_spec, wheel_ii_spec, wheel_iii_spec, reflector_b_spec, menu=menu)\n",
1018 "b(('a', 'a', 'b'))"
1019 ]
1020 },
1021 {
1022 "cell_type": "code",
1023 "execution_count": 36,
1024 "metadata": {
1025 "collapsed": true
1026 },
1027 "outputs": [],
1028 "source": [
1029 "b = Bombe(wheel_i_spec, wheel_ii_spec, wheel_iii_spec, reflector_b_spec, menu=menu)(('a', 'a', 'b'))"
1030 ]
1031 },
1032 {
1033 "cell_type": "code",
1034 "execution_count": 37,
1035 "metadata": {},
1036 "outputs": [
1037 {
1038 "data": {
1039 "text/plain": [
1040 "[('a', 'a', 'b')]"
1041 ]
1042 },
1043 "execution_count": 37,
1044 "metadata": {},
1045 "output_type": "execute_result"
1046 }
1047 ],
1048 "source": [
1049 "allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1050 "\n",
1051 "with multiprocessing.Pool() as pool:\n",
1052 " res = pool.map(Bombe(wheel_i_spec, wheel_ii_spec, wheel_iii_spec, reflector_b_spec, menu=menu),\n",
1053 " allwheels)\n",
1054 "[r[0] for r in res if r[1]]"
1055 ]
1056 },
1057 {
1058 "cell_type": "code",
1059 "execution_count": 38,
1060 "metadata": {
1061 "collapsed": true
1062 },
1063 "outputs": [],
1064 "source": [
1065 "def run_multi_bombe(wheel1_spec, wheel2_spec, wheel3_spec, reflector_spec, menu,\n",
1066 " start_signal=None, use_diagonal_board=True, \n",
1067 " verify_plugboard=True):\n",
1068 " allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1069 "\n",
1070 " with multiprocessing.Pool() as pool:\n",
1071 " res = pool.map(Bombe(wheel1_spec, wheel2_spec, wheel3_spec, \n",
1072 " reflector_spec, menu=menu, start_signal=start_signal, \n",
1073 " use_diagonal_board=use_diagonal_board, \n",
1074 " verify_plugboard=verify_plugboard),\n",
1075 " allwheels)\n",
1076 " return [r[0] for r in res if r[1]]"
1077 ]
1078 },
1079 {
1080 "cell_type": "code",
1081 "execution_count": 39,
1082 "metadata": {},
1083 "outputs": [
1084 {
1085 "data": {
1086 "text/plain": [
1087 "[('a', 'a', 'b')]"
1088 ]
1089 },
1090 "execution_count": 39,
1091 "metadata": {},
1092 "output_type": "execute_result"
1093 }
1094 ],
1095 "source": [
1096 "[r[0] for r in res if r[1]]"
1097 ]
1098 },
1099 {
1100 "cell_type": "code",
1101 "execution_count": 40,
1102 "metadata": {
1103 "collapsed": true
1104 },
1105 "outputs": [],
1106 "source": [
1107 "# Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm\n",
1108 "# Enigma simulation settings are \n",
1109 "# http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJFE;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX\n",
1110 "w_enigma = Enigma(reflector_b_spec, \n",
1111 " wheel_i_spec, wheel_i_pegs,\n",
1112 " wheel_v_spec, wheel_v_pegs,\n",
1113 " wheel_iii_spec, wheel_iii_pegs,\n",
1114 " 6, 20, 24,\n",
1115 " 'ua pf rq so ni ey bg hl tx zj')"
1116 ]
1117 },
1118 {
1119 "cell_type": "code",
1120 "execution_count": 41,
1121 "metadata": {},
1122 "outputs": [
1123 {
1124 "data": {
1125 "text/plain": [
1126 "('e', 'l', 'e')"
1127 ]
1128 },
1129 "execution_count": 41,
1130 "metadata": {},
1131 "output_type": "execute_result"
1132 }
1133 ],
1134 "source": [
1135 "w_enigma.set_wheels('j', 'e', 'b')\n",
1136 "tuple(unpos(p) for p in w_enigma.wheel_positions)"
1137 ]
1138 },
1139 {
1140 "cell_type": "code",
1141 "execution_count": 42,
1142 "metadata": {},
1143 "outputs": [
1144 {
1145 "data": {
1146 "text/plain": [
1147 "'dhnpforeeimgg'"
1148 ]
1149 },
1150 "execution_count": 42,
1151 "metadata": {},
1152 "output_type": "execute_result"
1153 }
1154 ],
1155 "source": [
1156 "w_enigma.set_wheels('j', 'e', 'b')\n",
1157 "pt = 'someplaintext'\n",
1158 "ct = w_enigma.encipher(pt)\n",
1159 "ct"
1160 ]
1161 },
1162 {
1163 "cell_type": "code",
1164 "execution_count": 43,
1165 "metadata": {},
1166 "outputs": [
1167 {
1168 "data": {
1169 "text/plain": [
1170 "('j', 'e', 'o')"
1171 ]
1172 },
1173 "execution_count": 43,
1174 "metadata": {},
1175 "output_type": "execute_result"
1176 }
1177 ],
1178 "source": [
1179 "w_enigma.wheel_positions_l"
1180 ]
1181 },
1182 {
1183 "cell_type": "code",
1184 "execution_count": 44,
1185 "metadata": {},
1186 "outputs": [
1187 {
1188 "data": {
1189 "text/plain": [
1190 "[MenuIem(before='s', after='d', number=1),\n",
1191 " MenuIem(before='o', after='h', number=2),\n",
1192 " MenuIem(before='m', after='n', number=3),\n",
1193 " MenuIem(before='e', after='p', number=4),\n",
1194 " MenuIem(before='p', after='f', number=5),\n",
1195 " MenuIem(before='l', after='o', number=6),\n",
1196 " MenuIem(before='a', after='r', number=7),\n",
1197 " MenuIem(before='i', after='e', number=8),\n",
1198 " MenuIem(before='n', after='e', number=9),\n",
1199 " MenuIem(before='t', after='i', number=10),\n",
1200 " MenuIem(before='e', after='m', number=11),\n",
1201 " MenuIem(before='x', after='g', number=12),\n",
1202 " MenuIem(before='t', after='g', number=13)]"
1203 ]
1204 },
1205 "execution_count": 44,
1206 "metadata": {},
1207 "output_type": "execute_result"
1208 }
1209 ],
1210 "source": [
1211 "w_menu = [MenuItem(p, c, i+1) for i, (p, c) in enumerate(zip(pt, ct))]\n",
1212 "w_menu"
1213 ]
1214 },
1215 {
1216 "cell_type": "code",
1217 "execution_count": 45,
1218 "metadata": {
1219 "scrolled": true
1220 },
1221 "outputs": [
1222 {
1223 "data": {
1224 "text/plain": [
1225 "[('a', 'y', 'm'),\n",
1226 " ('c', 'p', 'v'),\n",
1227 " ('c', 's', 'f'),\n",
1228 " ('c', 'w', 'j'),\n",
1229 " ('d', 'r', 'k'),\n",
1230 " ('e', 'l', 'f'),\n",
1231 " ('e', 's', 'v'),\n",
1232 " ('e', 'y', 'd'),\n",
1233 " ('e', 'y', 'o'),\n",
1234 " ('f', 'z', 'x'),\n",
1235 " ('g', 'b', 'l'),\n",
1236 " ('g', 'c', 'd'),\n",
1237 " ('g', 'c', 'f'),\n",
1238 " ('g', 'j', 'p'),\n",
1239 " ('h', 'c', 'i'),\n",
1240 " ('h', 'm', 'w'),\n",
1241 " ('h', 'o', 'd'),\n",
1242 " ('h', 'p', 'b'),\n",
1243 " ('h', 's', 't'),\n",
1244 " ('i', 'b', 's'),\n",
1245 " ('i', 'v', 'b'),\n",
1246 " ('j', 'y', 'u'),\n",
1247 " ('k', 'b', 'x'),\n",
1248 " ('k', 'f', 't'),\n",
1249 " ('k', 'l', 'e'),\n",
1250 " ('k', 'l', 'm'),\n",
1251 " ('k', 'r', 'z'),\n",
1252 " ('k', 's', 'p'),\n",
1253 " ('l', 'd', 'z'),\n",
1254 " ('l', 'i', 'y'),\n",
1255 " ('l', 'y', 'f'),\n",
1256 " ('m', 'b', 'h'),\n",
1257 " ('m', 'p', 'l'),\n",
1258 " ('n', 'l', 'r'),\n",
1259 " ('o', 'k', 'x'),\n",
1260 " ('p', 'a', 'g'),\n",
1261 " ('p', 'c', 'v'),\n",
1262 " ('p', 'f', 'o'),\n",
1263 " ('p', 'm', 'i'),\n",
1264 " ('p', 'x', 'n'),\n",
1265 " ('p', 'x', 'p'),\n",
1266 " ('q', 'q', 'n'),\n",
1267 " ('q', 'r', 'w'),\n",
1268 " ('q', 'v', 'l'),\n",
1269 " ('q', 'x', 't'),\n",
1270 " ('s', 'a', 'h'),\n",
1271 " ('s', 'h', 'v'),\n",
1272 " ('s', 'l', 'p'),\n",
1273 " ('s', 'l', 's'),\n",
1274 " ('u', 'r', 'h'),\n",
1275 " ('v', 'v', 'v'),\n",
1276 " ('v', 'x', 'a'),\n",
1277 " ('w', 'j', 'z'),\n",
1278 " ('w', 'k', 'u'),\n",
1279 " ('x', 'f', 'p'),\n",
1280 " ('x', 'j', 'n'),\n",
1281 " ('x', 'o', 'q'),\n",
1282 " ('x', 'x', 'x'),\n",
1283 " ('y', 'n', 'c'),\n",
1284 " ('y', 'r', 'f'),\n",
1285 " ('z', 't', 'y'),\n",
1286 " ('z', 'z', 'k')]"
1287 ]
1288 },
1289 "execution_count": 45,
1290 "metadata": {},
1291 "output_type": "execute_result"
1292 }
1293 ],
1294 "source": [
1295 "allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1296 "\n",
1297 "with multiprocessing.Pool() as pool:\n",
1298 " res = pool.map(Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, \n",
1299 " menu=w_menu, verify_plugboard=False),\n",
1300 " allwheels)\n",
1301 "[r[0] for r in res if r[1]]"
1302 ]
1303 },
1304 {
1305 "cell_type": "code",
1306 "execution_count": 46,
1307 "metadata": {},
1308 "outputs": [
1309 {
1310 "data": {
1311 "text/plain": [
1312 "62"
1313 ]
1314 },
1315 "execution_count": 46,
1316 "metadata": {},
1317 "output_type": "execute_result"
1318 }
1319 ],
1320 "source": [
1321 "len([r[0] for r in res if r[1]])"
1322 ]
1323 },
1324 {
1325 "cell_type": "code",
1326 "execution_count": 47,
1327 "metadata": {
1328 "scrolled": true
1329 },
1330 "outputs": [
1331 {
1332 "data": {
1333 "text/plain": [
1334 "[('c', 'p', 'v'),\n",
1335 " ('c', 's', 'f'),\n",
1336 " ('e', 'l', 'f'),\n",
1337 " ('g', 'c', 'f'),\n",
1338 " ('j', 'y', 'u'),\n",
1339 " ('o', 'k', 'x'),\n",
1340 " ('p', 'a', 'g'),\n",
1341 " ('q', 'q', 'n'),\n",
1342 " ('q', 'v', 'l'),\n",
1343 " ('q', 'x', 't'),\n",
1344 " ('s', 'l', 'p'),\n",
1345 " ('u', 'r', 'h'),\n",
1346 " ('y', 'n', 'c')]"
1347 ]
1348 },
1349 "execution_count": 47,
1350 "metadata": {},
1351 "output_type": "execute_result"
1352 }
1353 ],
1354 "source": [
1355 "allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1356 "\n",
1357 "with multiprocessing.Pool() as pool:\n",
1358 " res = pool.map(Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, \n",
1359 " menu=w_menu, verify_plugboard=True),\n",
1360 " allwheels)\n",
1361 "[r[0] for r in res if r[1]]"
1362 ]
1363 },
1364 {
1365 "cell_type": "code",
1366 "execution_count": 48,
1367 "metadata": {},
1368 "outputs": [
1369 {
1370 "data": {
1371 "text/plain": [
1372 "[('c', 'p', 'v'),\n",
1373 " ('c', 's', 'f'),\n",
1374 " ('e', 'l', 'f'),\n",
1375 " ('g', 'c', 'f'),\n",
1376 " ('j', 'y', 'u'),\n",
1377 " ('o', 'k', 'x'),\n",
1378 " ('p', 'a', 'g'),\n",
1379 " ('q', 'q', 'n'),\n",
1380 " ('q', 'v', 'l'),\n",
1381 " ('q', 'x', 't'),\n",
1382 " ('s', 'l', 'p'),\n",
1383 " ('u', 'r', 'h'),\n",
1384 " ('y', 'n', 'c')]"
1385 ]
1386 },
1387 "execution_count": 48,
1388 "metadata": {},
1389 "output_type": "execute_result"
1390 }
1391 ],
1392 "source": [
1393 "run_multi_bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, w_menu)"
1394 ]
1395 },
1396 {
1397 "cell_type": "code",
1398 "execution_count": 49,
1399 "metadata": {
1400 "collapsed": true
1401 },
1402 "outputs": [],
1403 "source": [
1404 "# allwheels = itertools.product(string.ascii_lowercase, repeat=3)\n",
1405 "\n",
1406 "# with multiprocessing.Pool() as pool:\n",
1407 "# res = pool.map(Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, \n",
1408 "# menu=w_menu, start_signal=Signal('t', 'x')),\n",
1409 "# allwheels)\n",
1410 "# [r[0] for r in res if r[1]]"
1411 ]
1412 },
1413 {
1414 "cell_type": "code",
1415 "execution_count": 50,
1416 "metadata": {},
1417 "outputs": [
1418 {
1419 "data": {
1420 "text/plain": [
1421 "13"
1422 ]
1423 },
1424 "execution_count": 50,
1425 "metadata": {},
1426 "output_type": "execute_result"
1427 }
1428 ],
1429 "source": [
1430 "len([r[0] for r in res if r[1]])"
1431 ]
1432 },
1433 {
1434 "cell_type": "code",
1435 "execution_count": 51,
1436 "metadata": {
1437 "collapsed": true
1438 },
1439 "outputs": [],
1440 "source": [
1441 "w_bombe = Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec, \n",
1442 " menu=w_menu)"
1443 ]
1444 },
1445 {
1446 "cell_type": "code",
1447 "execution_count": 52,
1448 "metadata": {},
1449 "outputs": [
1450 {
1451 "data": {
1452 "text/plain": [
1453 "Signal(bank='e', wire='e')"
1454 ]
1455 },
1456 "execution_count": 52,
1457 "metadata": {},
1458 "output_type": "execute_result"
1459 }
1460 ],
1461 "source": [
1462 "w_bombe.test_start"
1463 ]
1464 },
1465 {
1466 "cell_type": "code",
1467 "execution_count": 53,
1468 "metadata": {},
1469 "outputs": [
1470 {
1471 "data": {
1472 "text/plain": [
1473 "True"
1474 ]
1475 },
1476 "execution_count": 53,
1477 "metadata": {},
1478 "output_type": "execute_result"
1479 }
1480 ],
1481 "source": [
1482 "w_bombe.test(start_positions=('e', 'l', 'f'))"
1483 ]
1484 },
1485 {
1486 "cell_type": "code",
1487 "execution_count": 54,
1488 "metadata": {},
1489 "outputs": [
1490 {
1491 "data": {
1492 "text/plain": [
1493 "True"
1494 ]
1495 },
1496 "execution_count": 54,
1497 "metadata": {},
1498 "output_type": "execute_result"
1499 }
1500 ],
1501 "source": [
1502 "w_bombe.test(Signal('t', 'x'), ('e', 'l', 'f'))"
1503 ]
1504 },
1505 {
1506 "cell_type": "code",
1507 "execution_count": 55,
1508 "metadata": {},
1509 "outputs": [
1510 {
1511 "name": "stdout",
1512 "output_type": "stream",
1513 "text": [
1514 "True\n",
1515 "a : a.cdefghi..l.nopqrst.vwx..\n",
1516 "b : ....efghi...mnop.......x..\n",
1517 "c : a....fg.i..lmn.p.r.t...x..\n",
1518 "d : a...efghij.lmn...rstu..xyz\n",
1519 "e : ab.defghijklmnopqrstuvwxyz\n",
1520 "f : abcde.ghijklmnopqrstuvwxyz\n",
1521 "g : abcdef.hijklmnopqrstuvwxyz\n",
1522 "h : ab.defghi...mnopq.stuvwx..\n",
1523 "i : abcdefgh.jklmnopqrstuvwxyz\n",
1524 "j : ...defg.i...mn.p...t...x..\n",
1525 "k : ....efg.i..lmnop.r.t...x..\n",
1526 "l : a.cdefg.i.k.mnopqr.t..wxyz\n",
1527 "m : .bcdefghijklmnopqrstuvwxyz\n",
1528 "n : abcdefghijklmnopqr.tuvwxyz\n",
1529 "o : ab..efghi.klmnopqr.t...xyz\n",
1530 "p : abc.efghijklmnopqrstuvwxyz\n",
1531 "q : a...efghi..lmnop.r.t...x..\n",
1532 "r : a.cdefg.i.klmnopqrst..w..z\n",
1533 "s : a..defghi...m..p.rstuv.xyz\n",
1534 "t : a.cdefghijklmnopqrstuvwxyz\n",
1535 "u : ...defghi...mn.p..st...x..\n",
1536 "v : a...efghi...mn.p..st...x..\n",
1537 "w : a...efghi..lmn.p.r.t...x..\n",
1538 "x : abcdefghijklmnopq.stuvwxyz\n",
1539 "y : ...defg.i..lmnop..st...x..\n",
1540 "z : ...defg.i..lmnop.rst...x..\n"
1541 ]
1542 }
1543 ],
1544 "source": [
1545 "r = w_bombe.test(start_positions=('c', 'p', 'v'))\n",
1546 "print(r)\n",
1547 "for b in sorted(w_bombe.banks):\n",
1548 " print(b, ': ', end='')\n",
1549 " for w in sorted(w_bombe.banks[b]):\n",
1550 " if w_bombe.banks[b][w]:\n",
1551 " print(w, end='')\n",
1552 " else:\n",
1553 " print('.', end='')\n",
1554 " print('')"
1555 ]
1556 },
1557 {
1558 "cell_type": "code",
1559 "execution_count": 56,
1560 "metadata": {},
1561 "outputs": [
1562 {
1563 "name": "stdout",
1564 "output_type": "stream",
1565 "text": [
1566 "True\n",
1567 "a : abcdefghi..lmnop.rst.v.x.z\n",
1568 "b : a...ef.hi..lmnop.r.t...x..\n",
1569 "c : a..defg.i..lmn.p.rst...x..\n",
1570 "d : a.c.efghi.klmnopqrstu.wxyz\n",
1571 "e : abcdefghijklmnopqrstuvwx.z\n",
1572 "f : abcdefghijklmno.qrstuvwxyz\n",
1573 "g : a.cdefghijklmnopqrstuvwxyz\n",
1574 "h : ab.defghi...mnopqrstuvwxyz\n",
1575 "i : abcdefghijklm.opqrstuvwxyz\n",
1576 "j : ....efg.i..lmnop...t...x..\n",
1577 "k : ...defg.i..lmn.p..st...x..\n",
1578 "l : abcdefg.ijklmnopqrstuv.x..\n",
1579 "m : abcdefghijkl.nopqrstuvwxyz\n",
1580 "n : abcdefgh.jklmnopqrstuvwxyz\n",
1581 "o : ab.defghij.lmnop.r.tuvwxyz\n",
1582 "p : abcde.ghijklmnopqrstuvwxyz\n",
1583 "q : ...defghi..lmn.p..st...x..\n",
1584 "r : abcdefghi..lmnop.rst.v.x.z\n",
1585 "s : a.cdefghi.klmn.pqr.tuvwxyz\n",
1586 "t : abcdefghijklmnopqrstuvw.yz\n",
1587 "u : ...defghi..lmnop..st...x..\n",
1588 "v : a...efghi..lmnop.rst...x..\n",
1589 "w : ...defghi...mnop..st...x..\n",
1590 "x : abcdefghijklmnopqrs.uvwxyz\n",
1591 "y : ...d.fghi...mnop..st...x..\n",
1592 "z : a..defghi...mnop.rst...x..\n"
1593 ]
1594 }
1595 ],
1596 "source": [
1597 "r = w_bombe.test(start_positions=('e', 'l', 'f'))\n",
1598 "print(r)\n",
1599 "for b in sorted(w_bombe.banks):\n",
1600 " print(b, ': ', end='')\n",
1601 " for w in sorted(w_bombe.banks[b]):\n",
1602 " if w_bombe.banks[b][w]:\n",
1603 " print(w, end='')\n",
1604 " else:\n",
1605 " print('.', end='')\n",
1606 " print('')"
1607 ]
1608 },
1609 {
1610 "cell_type": "code",
1611 "execution_count": 57,
1612 "metadata": {},
1613 "outputs": [
1614 {
1615 "data": {
1616 "text/plain": [
1617 "{frozenset({'t', 'x'}),\n",
1618 " frozenset({'i', 'n'}),\n",
1619 " frozenset({'m'}),\n",
1620 " frozenset({'e', 'y'}),\n",
1621 " frozenset({'f', 'p'}),\n",
1622 " frozenset({'b', 'g'})}"
1623 ]
1624 },
1625 "execution_count": 57,
1626 "metadata": {},
1627 "output_type": "execute_result"
1628 }
1629 ],
1630 "source": [
1631 "ps = w_bombe.possible_plugboards()\n",
1632 "ps"
1633 ]
1634 },
1635 {
1636 "cell_type": "code",
1637 "execution_count": 58,
1638 "metadata": {},
1639 "outputs": [
1640 {
1641 "data": {
1642 "text/plain": [
1643 "True"
1644 ]
1645 },
1646 "execution_count": 58,
1647 "metadata": {},
1648 "output_type": "execute_result"
1649 }
1650 ],
1651 "source": [
1652 "all(s0.isdisjoint(s1) for s0 in ps for s1 in ps if s0 != s1)"
1653 ]
1654 },
1655 {
1656 "cell_type": "code",
1657 "execution_count": 59,
1658 "metadata": {},
1659 "outputs": [
1660 {
1661 "data": {
1662 "text/plain": [
1663 "({frozenset({1, 2}), frozenset({2, 3}), frozenset({3, 4})},\n",
1664 " frozenset({1, 2}),\n",
1665 " frozenset({3, 4}),\n",
1666 " frozenset({2, 3}))"
1667 ]
1668 },
1669 "execution_count": 59,
1670 "metadata": {},
1671 "output_type": "execute_result"
1672 }
1673 ],
1674 "source": [
1675 "s = set()\n",
1676 "f1 = frozenset((1, 2))\n",
1677 "f2 = frozenset((3, 4))\n",
1678 "f3 = frozenset((2, 3))\n",
1679 "s = s.union({f1})\n",
1680 "s = s.union({f2})\n",
1681 "s = s.union({f1})\n",
1682 "s = s.union({f3})\n",
1683 "s, f1, f2, f3"
1684 ]
1685 },
1686 {
1687 "cell_type": "code",
1688 "execution_count": 60,
1689 "metadata": {},
1690 "outputs": [
1691 {
1692 "data": {
1693 "text/plain": [
1694 "False"
1695 ]
1696 },
1697 "execution_count": 60,
1698 "metadata": {},
1699 "output_type": "execute_result"
1700 }
1701 ],
1702 "source": [
1703 "all(s0.isdisjoint(s1) for s0 in s for s1 in s if s0 != s1)"
1704 ]
1705 },
1706 {
1707 "cell_type": "code",
1708 "execution_count": 61,
1709 "metadata": {},
1710 "outputs": [
1711 {
1712 "data": {
1713 "text/plain": [
1714 "False"
1715 ]
1716 },
1717 "execution_count": 61,
1718 "metadata": {},
1719 "output_type": "execute_result"
1720 }
1721 ],
1722 "source": [
1723 "{1, 2}.isdisjoint({1, 6})"
1724 ]
1725 },
1726 {
1727 "cell_type": "markdown",
1728 "metadata": {
1729 "collapsed": true
1730 },
1731 "source": [
1732 "# Tsest"
1733 ]
1734 },
1735 {
1736 "cell_type": "code",
1737 "execution_count": 62,
1738 "metadata": {},
1739 "outputs": [
1740 {
1741 "data": {
1742 "text/plain": [
1743 "'slgncszxltkzebghstgywdmpr'"
1744 ]
1745 },
1746 "execution_count": 62,
1747 "metadata": {},
1748 "output_type": "execute_result"
1749 }
1750 ],
1751 "source": [
1752 "target_ct = ''.join(c.lower() for c in 'SLGNC SZXLT KZEBG HSTGY WDMPR' if c in string.ascii_letters)\n",
1753 "target_ct"
1754 ]
1755 },
1756 {
1757 "cell_type": "code",
1758 "execution_count": 63,
1759 "metadata": {},
1760 "outputs": [
1761 {
1762 "data": {
1763 "text/plain": [
1764 "'theyweredetectedbybritishshipsinclud'"
1765 ]
1766 },
1767 "execution_count": 63,
1768 "metadata": {},
1769 "output_type": "execute_result"
1770 }
1771 ],
1772 "source": [
1773 "target_pt = ''.join(c.lower() for c in 'Theyw erede tecte d byBri tishs hipsi nclud' if c in string.ascii_letters)\n",
1774 "target_pt"
1775 ]
1776 },
1777 {
1778 "cell_type": "code",
1779 "execution_count": 64,
1780 "metadata": {},
1781 "outputs": [
1782 {
1783 "data": {
1784 "text/plain": [
1785 "[MenuIem(before='w', after='c', number=1),\n",
1786 " MenuIem(before='e', after='s', number=2),\n",
1787 " MenuIem(before='r', after='z', number=3),\n",
1788 " MenuIem(before='e', after='x', number=4),\n",
1789 " MenuIem(before='d', after='l', number=5),\n",
1790 " MenuIem(before='e', after='t', number=6),\n",
1791 " MenuIem(before='t', after='k', number=7),\n",
1792 " MenuIem(before='e', after='z', number=8),\n",
1793 " MenuIem(before='c', after='e', number=9),\n",
1794 " MenuIem(before='t', after='b', number=10),\n",
1795 " MenuIem(before='e', after='g', number=11),\n",
1796 " MenuIem(before='d', after='h', number=12),\n",
1797 " MenuIem(before='b', after='s', number=13),\n",
1798 " MenuIem(before='y', after='t', number=14),\n",
1799 " MenuIem(before='b', after='g', number=15),\n",
1800 " MenuIem(before='r', after='y', number=16),\n",
1801 " MenuIem(before='i', after='w', number=17),\n",
1802 " MenuIem(before='t', after='d', number=18),\n",
1803 " MenuIem(before='i', after='m', number=19),\n",
1804 " MenuIem(before='s', after='p', number=20)]"
1805 ]
1806 },
1807 "execution_count": 64,
1808 "metadata": {},
1809 "output_type": "execute_result"
1810 }
1811 ],
1812 "source": [
1813 "tbt_menu = [MenuItem(p, c, i+1) for i, (p, c) in enumerate(zip(target_pt[4:24], target_ct[4:24]))]\n",
1814 "tbt_menu"
1815 ]
1816 },
1817 {
1818 "cell_type": "code",
1819 "execution_count": 65,
1820 "metadata": {
1821 "collapsed": true
1822 },
1823 "outputs": [],
1824 "source": [
1825 "tbt_bombe = Bombe(wheel_iii_spec, wheel_i_spec, wheel_ii_spec, reflector_b_spec, \n",
1826 " menu=tbt_menu)"
1827 ]
1828 },
1829 {
1830 "cell_type": "code",
1831 "execution_count": 66,
1832 "metadata": {},
1833 "outputs": [
1834 {
1835 "data": {
1836 "text/plain": [
1837 "[('k', 'r', 'n')]"
1838 ]
1839 },
1840 "execution_count": 66,
1841 "metadata": {},
1842 "output_type": "execute_result"
1843 }
1844 ],
1845 "source": [
1846 "tbt_wheel_posns = run_multi_bombe(wheel_iii_spec, wheel_i_spec, wheel_ii_spec, reflector_b_spec, tbt_menu)\n",
1847 "tbt_wheel_posns"
1848 ]
1849 },
1850 {
1851 "cell_type": "code",
1852 "execution_count": 67,
1853 "metadata": {},
1854 "outputs": [
1855 {
1856 "data": {
1857 "text/plain": [
1858 "Signal(bank='e', wire='e')"
1859 ]
1860 },
1861 "execution_count": 67,
1862 "metadata": {},
1863 "output_type": "execute_result"
1864 }
1865 ],
1866 "source": [
1867 "tbt_bombe.test_start"
1868 ]
1869 },
1870 {
1871 "cell_type": "code",
1872 "execution_count": 68,
1873 "metadata": {},
1874 "outputs": [
1875 {
1876 "name": "stdout",
1877 "output_type": "stream",
1878 "text": [
1879 "False\n",
1880 "a : abcdefghi..lmnop.rst.v.x.z\n",
1881 "b : a...ef.hi..lmnop.r.t...x..\n",
1882 "c : a..defg.i..lmn.p.rst...x..\n",
1883 "d : a.c.efghi.klmnopqrstu.wxyz\n",
1884 "e : abcdefghijklmnopqrstuvwx.z\n",
1885 "f : abcdefghijklmno.qrstuvwxyz\n",
1886 "g : a.cdefghijklmnopqrstuvwxyz\n",
1887 "h : ab.defghi...mnopqrstuvwxyz\n",
1888 "i : abcdefghijklm.opqrstuvwxyz\n",
1889 "j : ....efg.i..lmnop...t...x..\n",
1890 "k : ...defg.i..lmn.p..st...x..\n",
1891 "l : abcdefg.ijklmnopqrstuv.x..\n",
1892 "m : abcdefghijkl.nopqrstuvwxyz\n",
1893 "n : abcdefgh.jklmnopqrstuvwxyz\n",
1894 "o : ab.defghij.lmnop.r.tuvwxyz\n",
1895 "p : abcde.ghijklmnopqrstuvwxyz\n",
1896 "q : ...defghi..lmn.p..st...x..\n",
1897 "r : abcdefghi..lmnop.rst.v.x.z\n",
1898 "s : a.cdefghi.klmn.pqr.tuvwxyz\n",
1899 "t : abcdefghijklmnopqrstuvw.yz\n",
1900 "u : ...defghi..lmnop..st...x..\n",
1901 "v : a...efghi..lmnop.rst...x..\n",
1902 "w : ...defghi...mnop..st...x..\n",
1903 "x : abcdefghijklmnopqrs.uvwxyz\n",
1904 "y : ...d.fghi...mnop..st...x..\n",
1905 "z : a..defghi...mnop.rst...x..\n"
1906 ]
1907 }
1908 ],
1909 "source": [
1910 "r = tbt_bombe.test(start_positions=('l', 's', 'd'))\n",
1911 "print(r)\n",
1912 "for b in sorted(w_bombe.banks):\n",
1913 " print(b, ': ', end='')\n",
1914 " for w in sorted(w_bombe.banks[b]):\n",
1915 " if w_bombe.banks[b][w]:\n",
1916 " print(w, end='')\n",
1917 " else:\n",
1918 " print('.', end='')\n",
1919 " print('')\n"
1920 ]
1921 },
1922 {
1923 "cell_type": "code",
1924 "execution_count": 69,
1925 "metadata": {},
1926 "outputs": [
1927 {
1928 "data": {
1929 "text/plain": [
1930 "set()"
1931 ]
1932 },
1933 "execution_count": 69,
1934 "metadata": {},
1935 "output_type": "execute_result"
1936 }
1937 ],
1938 "source": [
1939 "ps = tbt_bombe.possible_plugboards()\n",
1940 "ps"
1941 ]
1942 },
1943 {
1944 "cell_type": "code",
1945 "execution_count": null,
1946 "metadata": {
1947 "collapsed": true
1948 },
1949 "outputs": [],
1950 "source": []
1951 }
1952 ],
1953 "metadata": {
1954 "kernelspec": {
1955 "display_name": "Python 3",
1956 "language": "python",
1957 "name": "python3"
1958 },
1959 "language_info": {
1960 "codemirror_mode": {
1961 "name": "ipython",
1962 "version": 3
1963 },
1964 "file_extension": ".py",
1965 "mimetype": "text/x-python",
1966 "name": "python",
1967 "nbconvert_exporter": "python",
1968 "pygments_lexer": "ipython3",
1969 "version": "3.5.3"
1970 }
1971 },
1972 "nbformat": 4,
1973 "nbformat_minor": 1
1974 }