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