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