Updated for challenge 9
[cipher-tools.git] / enigma-old.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "# Enigma machine\n",
8 "Specification from [Codes and Ciphers](http://www.codesandciphers.org.uk/enigma/rotorspec.htm) page.\n",
9 "\n",
10 "Example Enigma machines from [Louise Dale](http://enigma.louisedade.co.uk/enigma.html) (full simulation) and [EnigmaCo](http://enigmaco.de/enigma/enigma.html) (good animation of the wheels, but no ring settings).\n",
11 "\n",
12 "There's also the nice Enigma simulator for Android by [Franklin Heath](https://franklinheath.co.uk/2012/02/04/our-first-app-published-enigma-simulator/), available on the [Google Play store](https://play.google.com/store/apps/details?id=uk.co.franklinheath.enigmasim&hl=en_GB)."
13 ]
14 },
15 {
16 "cell_type": "code",
17 "execution_count": 1,
18 "metadata": {
19 "collapsed": true
20 },
21 "outputs": [],
22 "source": [
23 "import string\n",
24 "import collections\n",
25 "\n",
26 "cat = ''.join\n",
27 "\n",
28 "def clean(text): return cat(l.lower() for l in text if l in string.ascii_letters)\n",
29 "\n",
30 "def pos(letter): \n",
31 " if letter in string.ascii_lowercase:\n",
32 " return ord(letter) - ord('a')\n",
33 " elif letter in string.ascii_uppercase:\n",
34 " return ord(letter) - ord('A')\n",
35 " else:\n",
36 " return ''\n",
37 " \n",
38 "def unpos(number): return chr(number % 26 + ord('a'))"
39 ]
40 },
41 {
42 "cell_type": "code",
43 "execution_count": 2,
44 "metadata": {
45 "collapsed": true
46 },
47 "outputs": [],
48 "source": [
49 "wheel_i_spec = 'ekmflgdqvzntowyhxuspaibrcj'\n",
50 "wheel_ii_spec = 'ajdksiruxblhwtmcqgznpyfvoe'\n",
51 "wheel_iii_spec = 'bdfhjlcprtxvznyeiwgakmusqo'\n",
52 "wheel_iv_spec = 'esovpzjayquirhxlnftgkdcmwb'\n",
53 "wheel_v_spec = 'vzbrgityupsdnhlxawmjqofeck'\n",
54 "wheel_vi_spec = 'jpgvoumfyqbenhzrdkasxlictw'\n",
55 "wheel_vii_spec = 'nzjhgrcxmyswboufaivlpekqdt'\n",
56 "wheel_viii_spec = 'fkqhtlxocbjspdzramewniuygv'\n",
57 "beta_wheel_spec = 'leyjvcnixwpbqmdrtakzgfuhos'\n",
58 "gamma_wheel_spec = 'fsokanuerhmbtiycwlqpzxvgjd'\n",
59 "\n",
60 "wheel_i_pegs = ['q']\n",
61 "wheel_ii_pegs = ['e']\n",
62 "wheel_iii_pegs = ['v']\n",
63 "wheel_iv_pegs = ['j']\n",
64 "wheel_v_pegs = ['z']\n",
65 "wheel_vi_pegs = ['z', 'm']\n",
66 "wheel_vii_pegs = ['z', 'm']\n",
67 "wheel_viii_pegs = ['z', 'm']\n",
68 "\n",
69 "reflector_b_spec = 'ay br cu dh eq fs gl ip jx kn mo tz vw'\n",
70 "reflector_c_spec = 'af bv cp dj ei go hy kr lz mx nw tq su'"
71 ]
72 },
73 {
74 "cell_type": "code",
75 "execution_count": 3,
76 "metadata": {
77 "collapsed": true
78 },
79 "outputs": [],
80 "source": [
81 "class LetterTransformer(object):\n",
82 " def __init__(self, specification, raw_transform=False):\n",
83 " if raw_transform:\n",
84 " transform = specification\n",
85 " else:\n",
86 " transform = self.parse_specification(specification)\n",
87 " self.validate_transform(transform)\n",
88 " self.make_transform_map(transform)\n",
89 " \n",
90 " def parse_specification(self, specification):\n",
91 " return list(zip(string.ascii_lowercase, clean(specification)))\n",
92 " # return specification\n",
93 " \n",
94 " def validate_transform(self, transform):\n",
95 " \"\"\"A set of pairs, of from-to\"\"\"\n",
96 " if len(transform) != 26:\n",
97 " raise ValueError(\"Transform specification has {} pairs, requires 26\".\n",
98 " format(len(transform)))\n",
99 " for p in transform:\n",
100 " if len(p) != 2:\n",
101 " raise ValueError(\"Not all mappings in transform \"\n",
102 " \"have two elements\")\n",
103 " if len(set([p[0] for p in transform])) != 26:\n",
104 " raise ValueError(\"Transform specification must list 26 origin letters\") \n",
105 " if len(set([p[1] for p in transform])) != 26:\n",
106 " raise ValueError(\"Transform specification must list 26 destination letters\") \n",
107 "\n",
108 " def make_empty_transform(self):\n",
109 " self.forward_map = [0] * 26\n",
110 " self.backward_map = [0] * 26\n",
111 " \n",
112 " def make_transform_map(self, transform):\n",
113 " self.make_empty_transform()\n",
114 " for p in transform:\n",
115 " self.forward_map[pos(p[0])] = pos(p[1])\n",
116 " self.backward_map[pos(p[1])] = pos(p[0])\n",
117 " return self.forward_map, self.backward_map\n",
118 " \n",
119 " def forward(self, letter):\n",
120 " if letter in string.ascii_lowercase:\n",
121 " return unpos(self.forward_map[pos(letter)])\n",
122 " else:\n",
123 " return ''\n",
124 " \n",
125 " def backward(self, letter):\n",
126 " if letter in string.ascii_lowercase:\n",
127 " return unpos(self.backward_map[pos(letter)])\n",
128 " else:\n",
129 " return ''"
130 ]
131 },
132 {
133 "cell_type": "code",
134 "execution_count": 4,
135 "metadata": {},
136 "outputs": [
137 {
138 "data": {
139 "text/plain": [
140 "[('z', 'a'),\n",
141 " ('a', 'b'),\n",
142 " ('b', 'c'),\n",
143 " ('c', 'd'),\n",
144 " ('d', 'e'),\n",
145 " ('e', 'f'),\n",
146 " ('f', 'g'),\n",
147 " ('g', 'h'),\n",
148 " ('h', 'i'),\n",
149 " ('i', 'j'),\n",
150 " ('j', 'k'),\n",
151 " ('k', 'l'),\n",
152 " ('l', 'm'),\n",
153 " ('m', 'n'),\n",
154 " ('n', 'o'),\n",
155 " ('o', 'p'),\n",
156 " ('p', 'q'),\n",
157 " ('q', 'r'),\n",
158 " ('r', 's'),\n",
159 " ('s', 't'),\n",
160 " ('t', 'u'),\n",
161 " ('u', 'v'),\n",
162 " ('v', 'w'),\n",
163 " ('w', 'x'),\n",
164 " ('x', 'y'),\n",
165 " ('y', 'z')]"
166 ]
167 },
168 "execution_count": 4,
169 "metadata": {},
170 "output_type": "execute_result"
171 }
172 ],
173 "source": [
174 "tmap = [('z', 'a')] + [(l, string.ascii_lowercase[i+1]) for i, l in enumerate(string.ascii_lowercase[:-1])]\n",
175 "tmap"
176 ]
177 },
178 {
179 "cell_type": "code",
180 "execution_count": 5,
181 "metadata": {},
182 "outputs": [
183 {
184 "data": {
185 "text/plain": [
186 "'zyxwcabdefghijklmnopqrstuv'"
187 ]
188 },
189 "execution_count": 5,
190 "metadata": {},
191 "output_type": "execute_result"
192 }
193 ],
194 "source": [
195 "cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase))"
196 ]
197 },
198 {
199 "cell_type": "code",
200 "execution_count": 6,
201 "metadata": {
202 "collapsed": true,
203 "scrolled": true
204 },
205 "outputs": [],
206 "source": [
207 "tmap2 = list(zip(string.ascii_lowercase, cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase))))"
208 ]
209 },
210 {
211 "cell_type": "code",
212 "execution_count": 7,
213 "metadata": {
214 "scrolled": true
215 },
216 "outputs": [
217 {
218 "data": {
219 "text/plain": [
220 "([1,\n",
221 " 2,\n",
222 " 3,\n",
223 " 4,\n",
224 " 5,\n",
225 " 6,\n",
226 " 7,\n",
227 " 8,\n",
228 " 9,\n",
229 " 10,\n",
230 " 11,\n",
231 " 12,\n",
232 " 13,\n",
233 " 14,\n",
234 " 15,\n",
235 " 16,\n",
236 " 17,\n",
237 " 18,\n",
238 " 19,\n",
239 " 20,\n",
240 " 21,\n",
241 " 22,\n",
242 " 23,\n",
243 " 24,\n",
244 " 25,\n",
245 " 0],\n",
246 " [25,\n",
247 " 0,\n",
248 " 1,\n",
249 " 2,\n",
250 " 3,\n",
251 " 4,\n",
252 " 5,\n",
253 " 6,\n",
254 " 7,\n",
255 " 8,\n",
256 " 9,\n",
257 " 10,\n",
258 " 11,\n",
259 " 12,\n",
260 " 13,\n",
261 " 14,\n",
262 " 15,\n",
263 " 16,\n",
264 " 17,\n",
265 " 18,\n",
266 " 19,\n",
267 " 20,\n",
268 " 21,\n",
269 " 22,\n",
270 " 23,\n",
271 " 24])"
272 ]
273 },
274 "execution_count": 7,
275 "metadata": {},
276 "output_type": "execute_result"
277 }
278 ],
279 "source": [
280 "lt = LetterTransformer(tmap, raw_transform = True)\n",
281 "assert(lt.forward_map == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0])\n",
282 "assert(lt.backward_map == [25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24])\n",
283 "lt.forward_map, lt.backward_map"
284 ]
285 },
286 {
287 "cell_type": "code",
288 "execution_count": 8,
289 "metadata": {
290 "scrolled": true
291 },
292 "outputs": [
293 {
294 "data": {
295 "text/plain": [
296 "([25,\n",
297 " 24,\n",
298 " 23,\n",
299 " 22,\n",
300 " 2,\n",
301 " 0,\n",
302 " 1,\n",
303 " 3,\n",
304 " 4,\n",
305 " 5,\n",
306 " 6,\n",
307 " 7,\n",
308 " 8,\n",
309 " 9,\n",
310 " 10,\n",
311 " 11,\n",
312 " 12,\n",
313 " 13,\n",
314 " 14,\n",
315 " 15,\n",
316 " 16,\n",
317 " 17,\n",
318 " 18,\n",
319 " 19,\n",
320 " 20,\n",
321 " 21],\n",
322 " [5,\n",
323 " 6,\n",
324 " 4,\n",
325 " 7,\n",
326 " 8,\n",
327 " 9,\n",
328 " 10,\n",
329 " 11,\n",
330 " 12,\n",
331 " 13,\n",
332 " 14,\n",
333 " 15,\n",
334 " 16,\n",
335 " 17,\n",
336 " 18,\n",
337 " 19,\n",
338 " 20,\n",
339 " 21,\n",
340 " 22,\n",
341 " 23,\n",
342 " 24,\n",
343 " 25,\n",
344 " 3,\n",
345 " 2,\n",
346 " 1,\n",
347 " 0])"
348 ]
349 },
350 "execution_count": 8,
351 "metadata": {},
352 "output_type": "execute_result"
353 }
354 ],
355 "source": [
356 "lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase)))\n",
357 "assert(lt.forward_map == [25, 24, 23, 22, 2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])\n",
358 "assert(lt.backward_map == [5, 6, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 3, 2, 1, 0])\n",
359 "assert(cat(lt.forward(l) for l in string.ascii_lowercase) == 'zyxwcabdefghijklmnopqrstuv')\n",
360 "assert(cat(lt.backward(l) for l in string.ascii_lowercase) == 'fgehijklmnopqrstuvwxyzdcba')\n",
361 "lt.forward_map, lt.backward_map"
362 ]
363 },
364 {
365 "cell_type": "code",
366 "execution_count": 9,
367 "metadata": {},
368 "outputs": [
369 {
370 "data": {
371 "text/plain": [
372 "'zyxwcabdefghijklmnopqrstuv'"
373 ]
374 },
375 "execution_count": 9,
376 "metadata": {},
377 "output_type": "execute_result"
378 }
379 ],
380 "source": [
381 "cat(lt.forward(l) for l in string.ascii_lowercase)"
382 ]
383 },
384 {
385 "cell_type": "code",
386 "execution_count": 10,
387 "metadata": {},
388 "outputs": [
389 {
390 "data": {
391 "text/plain": [
392 "'fgehijklmnopqrstuvwxyzdcba'"
393 ]
394 },
395 "execution_count": 10,
396 "metadata": {},
397 "output_type": "execute_result"
398 }
399 ],
400 "source": [
401 "cat(lt.backward(l) for l in string.ascii_lowercase)"
402 ]
403 },
404 {
405 "cell_type": "code",
406 "execution_count": 11,
407 "metadata": {
408 "collapsed": true
409 },
410 "outputs": [],
411 "source": [
412 "class Plugboard(LetterTransformer):\n",
413 " def parse_specification(self, specification):\n",
414 " return [tuple(clean(p)) for p in specification.split()]\n",
415 " \n",
416 " def validate_transform(self, transform):\n",
417 " \"\"\"A set of pairs, of from-to\"\"\"\n",
418 " for p in transform:\n",
419 " if len(p) != 2:\n",
420 " raise ValueError(\"Not all mappings in transform\"\n",
421 " \"have two elements\")\n",
422 " \n",
423 " def make_empty_transform(self):\n",
424 " self.forward_map = list(range(26))\n",
425 " self.backward_map = list(range(26))\n",
426 " \n",
427 " def make_transform_map(self, transform):\n",
428 " expanded_transform = transform + [tuple(reversed(p)) for p in transform]\n",
429 " return super(Plugboard, self).make_transform_map(expanded_transform)"
430 ]
431 },
432 {
433 "cell_type": "code",
434 "execution_count": 12,
435 "metadata": {
436 "collapsed": true
437 },
438 "outputs": [],
439 "source": [
440 "pb = Plugboard([('a', 'z'), ('b', 'y')], raw_transform=True)"
441 ]
442 },
443 {
444 "cell_type": "code",
445 "execution_count": 13,
446 "metadata": {},
447 "outputs": [
448 {
449 "data": {
450 "text/plain": [
451 "'zycdefghijklmnopqrstuvwxba'"
452 ]
453 },
454 "execution_count": 13,
455 "metadata": {},
456 "output_type": "execute_result"
457 }
458 ],
459 "source": [
460 "cat(pb.forward(l) for l in string.ascii_lowercase)"
461 ]
462 },
463 {
464 "cell_type": "code",
465 "execution_count": 14,
466 "metadata": {},
467 "outputs": [
468 {
469 "data": {
470 "text/plain": [
471 "'zycdefghijklmnopqrstuvwxba'"
472 ]
473 },
474 "execution_count": 14,
475 "metadata": {},
476 "output_type": "execute_result"
477 }
478 ],
479 "source": [
480 "cat(pb.backward(l) for l in string.ascii_lowercase)"
481 ]
482 },
483 {
484 "cell_type": "code",
485 "execution_count": 15,
486 "metadata": {
487 "collapsed": true
488 },
489 "outputs": [],
490 "source": [
491 "pb = Plugboard('az by')"
492 ]
493 },
494 {
495 "cell_type": "code",
496 "execution_count": 16,
497 "metadata": {},
498 "outputs": [
499 {
500 "data": {
501 "text/plain": [
502 "('zycdefghijklmnopqrstuvwxba', 'zycdefghijklmnopqrstuvwxba')"
503 ]
504 },
505 "execution_count": 16,
506 "metadata": {},
507 "output_type": "execute_result"
508 }
509 ],
510 "source": [
511 "cat(pb.forward(l) for l in string.ascii_lowercase), cat(pb.backward(l) for l in string.ascii_lowercase)"
512 ]
513 },
514 {
515 "cell_type": "code",
516 "execution_count": 17,
517 "metadata": {},
518 "outputs": [
519 {
520 "data": {
521 "text/plain": [
522 "('ugcdypblnzkhmisfrqoxavwtej', 'ugcdypblnzkhmisfrqoxavwtej')"
523 ]
524 },
525 "execution_count": 17,
526 "metadata": {},
527 "output_type": "execute_result"
528 }
529 ],
530 "source": [
531 "pb = Plugboard('ua pf rq so ni ey bg hl tx zj'.upper())\n",
532 "assert(pb.forward_map == pb.backward_map)\n",
533 "assert(pb.forward_map == [20, 6, 2, 3, 24, 15, 1, 11, 13, 25, 10, 7, 12, 8, 18, 5, 17, 16, 14, 23, 0, 21, 22, 19, 4, 9])\n",
534 "assert(cat(pb.forward(l) for l in string.ascii_lowercase) == 'ugcdypblnzkhmisfrqoxavwtej')\n",
535 "assert(cat(pb.backward(l) for l in string.ascii_lowercase) == 'ugcdypblnzkhmisfrqoxavwtej')\n",
536 "cat(pb.forward(l) for l in string.ascii_lowercase), cat(pb.backward(l) for l in string.ascii_lowercase)"
537 ]
538 },
539 {
540 "cell_type": "code",
541 "execution_count": 18,
542 "metadata": {
543 "collapsed": true
544 },
545 "outputs": [],
546 "source": [
547 "class Reflector(Plugboard):\n",
548 " def validate_transform(self, transform):\n",
549 " if len(transform) != 13:\n",
550 " raise ValueError(\"Reflector specification has {} pairs, requires 13\".\n",
551 " format(len(transform)))\n",
552 " if len(set([p[0] for p in transform] + \n",
553 " [p[1] for p in transform])) != 26:\n",
554 " raise ValueError(\"Reflector specification does not contain 26 letters\")\n",
555 " try:\n",
556 " super(Reflector, self).validate_transform(transform)\n",
557 " except ValueError as v:\n",
558 " raise ValueError(\"Not all mappings in reflector have two elements\")"
559 ]
560 },
561 {
562 "cell_type": "code",
563 "execution_count": 19,
564 "metadata": {},
565 "outputs": [
566 {
567 "data": {
568 "text/plain": [
569 "[('a', 'y'),\n",
570 " ('b', 'r'),\n",
571 " ('c', 'u'),\n",
572 " ('d', 'h'),\n",
573 " ('e', 'q'),\n",
574 " ('f', 's'),\n",
575 " ('g', 'l'),\n",
576 " ('i', 'p'),\n",
577 " ('j', 'x'),\n",
578 " ('k', 'n'),\n",
579 " ('m', 'o'),\n",
580 " ('t', 'z'),\n",
581 " ('v', 'w')]"
582 ]
583 },
584 "execution_count": 19,
585 "metadata": {},
586 "output_type": "execute_result"
587 }
588 ],
589 "source": [
590 "# reflector_b_text = '(AY) (BR) (CU) (DH) (EQ) (FS) (GL) (IP) (JX) (KN) (MO) (TZ) (VW)'\n",
591 "reflector_b_l = [tuple(clean(p)) for p in reflector_b_spec.split()]\n",
592 "reflector_b_l"
593 ]
594 },
595 {
596 "cell_type": "code",
597 "execution_count": 20,
598 "metadata": {
599 "collapsed": true
600 },
601 "outputs": [],
602 "source": [
603 "reflector_b = Reflector(reflector_b_spec)\n",
604 "assert(reflector_b.forward_map == reflector_b.backward_map)\n",
605 "assert(reflector_b.forward_map == [24, 17, 20, 7, 16, 18, 11, 3, 15, 23, 13, 6, 14, 10, 12, 8, 4, 1, 5, 25, 2, 22, 21, 9, 0, 19])\n",
606 "assert(cat(reflector_b.forward(l) for l in string.ascii_lowercase) == 'yruhqsldpxngokmiebfzcwvjat')\n",
607 "assert(cat(reflector_b.backward(l) for l in string.ascii_lowercase) == 'yruhqsldpxngokmiebfzcwvjat')"
608 ]
609 },
610 {
611 "cell_type": "code",
612 "execution_count": 21,
613 "metadata": {},
614 "outputs": [
615 {
616 "data": {
617 "text/plain": [
618 "'yruhqsldpxngokmiebfzcwvjat'"
619 ]
620 },
621 "execution_count": 21,
622 "metadata": {},
623 "output_type": "execute_result"
624 }
625 ],
626 "source": [
627 "cat(reflector_b.forward(l) for l in string.ascii_lowercase)"
628 ]
629 },
630 {
631 "cell_type": "code",
632 "execution_count": 22,
633 "metadata": {
634 "collapsed": true
635 },
636 "outputs": [],
637 "source": [
638 "reflector_c = Reflector(reflector_c_spec)"
639 ]
640 },
641 {
642 "cell_type": "code",
643 "execution_count": 23,
644 "metadata": {},
645 "outputs": [
646 {
647 "data": {
648 "text/plain": [
649 "'fvpjiaoyedrzxwgctkuqsbnmhl'"
650 ]
651 },
652 "execution_count": 23,
653 "metadata": {},
654 "output_type": "execute_result"
655 }
656 ],
657 "source": [
658 "cat(reflector_c.forward(l) for l in string.ascii_lowercase)"
659 ]
660 },
661 {
662 "cell_type": "code",
663 "execution_count": 24,
664 "metadata": {
665 "collapsed": true
666 },
667 "outputs": [],
668 "source": [
669 "class SimpleWheel(LetterTransformer):\n",
670 " def __init__(self, transform, position='a', raw_transform=False):\n",
671 " super(SimpleWheel, self).__init__(transform, raw_transform)\n",
672 " self.set_position(position)\n",
673 " \n",
674 " def __getattribute__(self,name):\n",
675 " if name=='position_l':\n",
676 " return unpos(self.position)\n",
677 " else:\n",
678 " return object.__getattribute__(self, name)\n",
679 " \n",
680 " def set_position(self, position):\n",
681 " self.position = ord(position) - ord('a')\n",
682 " \n",
683 " def forward(self, letter):\n",
684 " if letter in string.ascii_lowercase:\n",
685 " return unpos((self.forward_map[(pos(letter) + self.position) % 26] - self.position))\n",
686 " else:\n",
687 " return ''\n",
688 " \n",
689 " def backward(self, letter):\n",
690 " if letter in string.ascii_lowercase:\n",
691 " return unpos((self.backward_map[(pos(letter) + self.position) % 26] - self.position))\n",
692 " else:\n",
693 " return ''\n",
694 " \n",
695 " def advance(self):\n",
696 " self.position = (self.position + 1) % 26\n",
697 " return self.position"
698 ]
699 },
700 {
701 "cell_type": "code",
702 "execution_count": 25,
703 "metadata": {
704 "scrolled": true
705 },
706 "outputs": [
707 {
708 "data": {
709 "text/plain": [
710 "[('a', 'e'),\n",
711 " ('b', 'k'),\n",
712 " ('c', 'm'),\n",
713 " ('d', 'f'),\n",
714 " ('e', 'l'),\n",
715 " ('f', 'g'),\n",
716 " ('g', 'd'),\n",
717 " ('h', 'q'),\n",
718 " ('i', 'v'),\n",
719 " ('j', 'z'),\n",
720 " ('k', 'n'),\n",
721 " ('l', 't'),\n",
722 " ('m', 'o'),\n",
723 " ('n', 'w'),\n",
724 " ('o', 'y'),\n",
725 " ('p', 'h'),\n",
726 " ('q', 'x'),\n",
727 " ('r', 'u'),\n",
728 " ('s', 's'),\n",
729 " ('t', 'p'),\n",
730 " ('u', 'a'),\n",
731 " ('v', 'i'),\n",
732 " ('w', 'b'),\n",
733 " ('x', 'r'),\n",
734 " ('y', 'c'),\n",
735 " ('z', 'j')]"
736 ]
737 },
738 "execution_count": 25,
739 "metadata": {},
740 "output_type": "execute_result"
741 }
742 ],
743 "source": [
744 "rotor_1_transform = list(zip(string.ascii_lowercase, 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.lower()))\n",
745 "rotor_1_transform"
746 ]
747 },
748 {
749 "cell_type": "code",
750 "execution_count": 26,
751 "metadata": {
752 "collapsed": true
753 },
754 "outputs": [],
755 "source": [
756 "rotor_1_transform = list(zip(string.ascii_lowercase, 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.lower()))\n",
757 "wheel_1 = SimpleWheel(rotor_1_transform, raw_transform=True)\n",
758 "assert(cat(wheel_1.forward(l) for l in string.ascii_lowercase) == 'ekmflgdqvzntowyhxuspaibrcj')\n",
759 "assert(cat(wheel_1.backward(l) for l in string.ascii_lowercase) == 'uwygadfpvzbeckmthxslrinqoj')"
760 ]
761 },
762 {
763 "cell_type": "code",
764 "execution_count": 27,
765 "metadata": {},
766 "outputs": [
767 {
768 "data": {
769 "text/plain": [
770 "('ekmflgdqvzntowyhxuspaibrcj', 'uwygadfpvzbeckmthxslrinqoj')"
771 ]
772 },
773 "execution_count": 27,
774 "metadata": {},
775 "output_type": "execute_result"
776 }
777 ],
778 "source": [
779 "cat(wheel_1.forward(l) for l in string.ascii_lowercase), cat(wheel_1.backward(l) for l in string.ascii_lowercase)"
780 ]
781 },
782 {
783 "cell_type": "code",
784 "execution_count": 28,
785 "metadata": {},
786 "outputs": [
787 {
788 "data": {
789 "text/plain": [
790 "'a'"
791 ]
792 },
793 "execution_count": 28,
794 "metadata": {},
795 "output_type": "execute_result"
796 }
797 ],
798 "source": [
799 "wheel_1.position_l"
800 ]
801 },
802 {
803 "cell_type": "code",
804 "execution_count": 29,
805 "metadata": {
806 "collapsed": true
807 },
808 "outputs": [],
809 "source": [
810 "wheel_2 = SimpleWheel(wheel_ii_spec)\n",
811 "assert(cat(wheel_2.forward(l) for l in string.ascii_lowercase) == 'ajdksiruxblhwtmcqgznpyfvoe')\n",
812 "assert(cat(wheel_2.backward(l) for l in string.ascii_lowercase) == 'ajpczwrlfbdkotyuqgenhxmivs')"
813 ]
814 },
815 {
816 "cell_type": "code",
817 "execution_count": 30,
818 "metadata": {},
819 "outputs": [
820 {
821 "data": {
822 "text/plain": [
823 "('ajdksiruxblhwtmcqgznpyfvoe', 'ajpczwrlfbdkotyuqgenhxmivs')"
824 ]
825 },
826 "execution_count": 30,
827 "metadata": {},
828 "output_type": "execute_result"
829 }
830 ],
831 "source": [
832 "cat(wheel_2.forward(l) for l in string.ascii_lowercase), cat(wheel_2.backward(l) for l in string.ascii_lowercase)"
833 ]
834 },
835 {
836 "cell_type": "code",
837 "execution_count": 31,
838 "metadata": {},
839 "outputs": [
840 {
841 "data": {
842 "text/plain": [
843 "('bdfhjlcprtxvznyeiwgakmusqo', 'tagbpcsdqeufvnzhyixjwlrkom')"
844 ]
845 },
846 "execution_count": 31,
847 "metadata": {},
848 "output_type": "execute_result"
849 }
850 ],
851 "source": [
852 "wheel_3 = SimpleWheel(wheel_iii_spec)\n",
853 "wheel_3.set_position('a')\n",
854 "wheel_3.advance()\n",
855 "assert(cat(wheel_3.forward(l) for l in string.ascii_lowercase) == 'cegikboqswuymxdhvfzjltrpna')\n",
856 "assert(cat(wheel_3.backward(l) for l in string.ascii_lowercase) == 'zfaobrcpdteumygxhwivkqjnls')\n",
857 "assert(wheel_3.position == 1)\n",
858 "assert(wheel_3.position_l == 'b')\n",
859 "\n",
860 "for _ in range(24): wheel_3.advance()\n",
861 "assert(wheel_3.position == 25)\n",
862 "assert(wheel_3.position_l == 'z')\n",
863 "assert(cat(wheel_3.forward(l) for l in string.ascii_lowercase) == 'pcegikmdqsuywaozfjxhblnvtr')\n",
864 "assert(cat(wheel_3.backward(l) for l in string.ascii_lowercase) == 'nubhcqdterfvgwoaizjykxmslp')\n",
865 "\n",
866 "wheel_3.advance()\n",
867 "assert(wheel_3.position == 0)\n",
868 "assert(wheel_3.position_l == 'a')\n",
869 "assert(cat(wheel_3.forward(l) for l in string.ascii_lowercase) == 'bdfhjlcprtxvznyeiwgakmusqo')\n",
870 "assert(cat(wheel_3.backward(l) for l in string.ascii_lowercase) == 'tagbpcsdqeufvnzhyixjwlrkom')\n",
871 "\n",
872 "cat(wheel_3.forward(l) for l in string.ascii_lowercase), cat(wheel_3.backward(l) for l in string.ascii_lowercase)"
873 ]
874 },
875 {
876 "cell_type": "code",
877 "execution_count": 32,
878 "metadata": {
879 "collapsed": true
880 },
881 "outputs": [],
882 "source": [
883 "class Wheel(SimpleWheel):\n",
884 " def __init__(self, transform, ring_peg_letters, ring_setting=1, position='a', raw_transform=False):\n",
885 " self.ring_peg_letters = ring_peg_letters\n",
886 " self.ring_setting = ring_setting\n",
887 " super(Wheel, self).__init__(transform, position=position, raw_transform=raw_transform)\n",
888 " self.set_position(position)\n",
889 " \n",
890 " def __getattribute__(self,name):\n",
891 " if name=='position_l':\n",
892 " return unpos(self.position + self.ring_setting - 1)\n",
893 " else:\n",
894 " return object.__getattribute__(self, name)\n",
895 "\n",
896 " def set_position(self, position):\n",
897 " self.position = (pos(position) - self.ring_setting + 1) % 26\n",
898 " # self.position_l = position\n",
899 " self.peg_positions = [(pos(p) - pos(position)) % 26 for p in self.ring_peg_letters]\n",
900 " \n",
901 " def advance(self):\n",
902 " super(Wheel, self).advance()\n",
903 " self.peg_positions = [(p - 1) % 26 for p in self.peg_positions]\n",
904 " # self.position_l = unpos(self.position + self.ring_setting - 1)\n",
905 " return self.position"
906 ]
907 },
908 {
909 "cell_type": "code",
910 "execution_count": 33,
911 "metadata": {
912 "collapsed": true
913 },
914 "outputs": [],
915 "source": [
916 "wheel_3 = Wheel(wheel_iii_spec, wheel_iii_pegs, position='b', ring_setting=1)"
917 ]
918 },
919 {
920 "cell_type": "code",
921 "execution_count": 34,
922 "metadata": {},
923 "outputs": [
924 {
925 "data": {
926 "text/plain": [
927 "(1, [20])"
928 ]
929 },
930 "execution_count": 34,
931 "metadata": {},
932 "output_type": "execute_result"
933 }
934 ],
935 "source": [
936 "wheel_3.position, wheel_3.peg_positions"
937 ]
938 },
939 {
940 "cell_type": "code",
941 "execution_count": 35,
942 "metadata": {},
943 "outputs": [
944 {
945 "data": {
946 "text/plain": [
947 "(25, [24, 11])"
948 ]
949 },
950 "execution_count": 35,
951 "metadata": {},
952 "output_type": "execute_result"
953 }
954 ],
955 "source": [
956 "wheel_6 = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', ring_setting=3)\n",
957 "wheel_6.position, wheel_6.peg_positions"
958 ]
959 },
960 {
961 "cell_type": "code",
962 "execution_count": 36,
963 "metadata": {
964 "scrolled": true
965 },
966 "outputs": [
967 {
968 "name": "stdout",
969 "output_type": "stream",
970 "text": [
971 "0 [23, 10]\n",
972 "1 [22, 9]\n",
973 "2 [21, 8]\n",
974 "3 [20, 7]\n",
975 "4 [19, 6]\n",
976 "5 [18, 5]\n",
977 "6 [17, 4]\n",
978 "7 [16, 3]\n",
979 "8 [15, 2]\n",
980 "9 [14, 1]\n",
981 "10 [13, 0]\n",
982 "11 [12, 25]\n",
983 "12 [11, 24]\n",
984 "13 [10, 23]\n",
985 "14 [9, 22]\n",
986 "15 [8, 21]\n",
987 "16 [7, 20]\n",
988 "17 [6, 19]\n",
989 "18 [5, 18]\n",
990 "19 [4, 17]\n",
991 "20 [3, 16]\n",
992 "21 [2, 15]\n",
993 "22 [1, 14]\n",
994 "23 [0, 13]\n",
995 "24 [25, 12]\n",
996 "25 [24, 11]\n",
997 "0 [23, 10]\n"
998 ]
999 }
1000 ],
1001 "source": [
1002 "for _ in range(27):\n",
1003 " wheel_6.advance()\n",
1004 " print(wheel_6.position, wheel_6.peg_positions)"
1005 ]
1006 },
1007 {
1008 "cell_type": "code",
1009 "execution_count": 37,
1010 "metadata": {
1011 "collapsed": true
1012 },
1013 "outputs": [],
1014 "source": [
1015 "wheel_3 = Wheel(wheel_iii_spec, wheel_iii_pegs, position='b', ring_setting=1)\n",
1016 "assert(wheel_3.position == 1)\n",
1017 "assert(wheel_3.peg_positions == [20])\n",
1018 "assert(wheel_3.position_l == 'b')\n",
1019 "wheel_3.advance()\n",
1020 "assert(wheel_3.position == 2)\n",
1021 "assert(wheel_3.peg_positions == [19])\n",
1022 "assert(wheel_3.position_l == 'c')"
1023 ]
1024 },
1025 {
1026 "cell_type": "code",
1027 "execution_count": 38,
1028 "metadata": {
1029 "collapsed": true
1030 },
1031 "outputs": [],
1032 "source": [
1033 "wheel_6 = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', ring_setting=3)\n",
1034 "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'xkqhwpvngzrcfoiaselbtymjdu')\n",
1035 "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'ptlyrmidoxbswhnfckquzgeavj')\n",
1036 "assert(wheel_6.position == 25)\n",
1037 "assert(11 in wheel_6.peg_positions)\n",
1038 "assert(24 in wheel_6.peg_positions)\n",
1039 "assert(wheel_6.position_l == 'b')\n",
1040 "\n",
1041 "wheel_6.advance()\n",
1042 "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'jpgvoumfyqbenhzrdkasxlictw')\n",
1043 "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'skxqlhcnwarvgmebjptyfdzuio')\n",
1044 "assert(wheel_6.position == 0)\n",
1045 "assert(10 in wheel_6.peg_positions)\n",
1046 "assert(23 in wheel_6.peg_positions)\n",
1047 "assert(wheel_6.position_l == 'c')\n",
1048 "\n",
1049 "for _ in range(22): wheel_6.advance()\n",
1050 "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'mgxantkzsyqjcufirldvhoewbp')\n",
1051 "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'dymswobuplgraevzkqifntxcjh')\n",
1052 "assert(wheel_6.position == 22)\n",
1053 "assert(1 in wheel_6.peg_positions)\n",
1054 "assert(14 in wheel_6.peg_positions)\n",
1055 "assert(wheel_6.position_l == 'y')\n",
1056 "\n",
1057 "wheel_6.advance()\n",
1058 "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'fwzmsjyrxpibtehqkcugndvaol')\n",
1059 "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'xlrvnatokfqzduyjphemswbigc')\n",
1060 "assert(wheel_6.position == 23)\n",
1061 "assert(0 in wheel_6.peg_positions)\n",
1062 "assert(13 in wheel_6.peg_positions)\n",
1063 "assert(wheel_6.position_l == 'z')\n",
1064 "\n",
1065 "wheel_6.advance()\n",
1066 "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'vylrixqwohasdgpjbtfmcuznke')\n",
1067 "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'kqumzsnjepyctxiogdlrvahfbw')\n",
1068 "assert(wheel_6.position == 24)\n",
1069 "assert(25 in wheel_6.peg_positions)\n",
1070 "assert(12 in wheel_6.peg_positions)\n",
1071 "assert(wheel_6.position_l == 'a')\n",
1072 "\n",
1073 "wheel_6.advance()\n",
1074 "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'xkqhwpvngzrcfoiaselbtymjdu')\n",
1075 "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'ptlyrmidoxbswhnfckquzgeavj')\n",
1076 "assert(wheel_6.position == 25)\n",
1077 "assert(24 in wheel_6.peg_positions)\n",
1078 "assert(11 in wheel_6.peg_positions)\n",
1079 "assert(wheel_6.position_l == 'b')\n",
1080 "\n",
1081 "wheel_6.advance()\n",
1082 "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'jpgvoumfyqbenhzrdkasxlictw')\n",
1083 "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'skxqlhcnwarvgmebjptyfdzuio')\n",
1084 "assert(wheel_6.position == 0)\n",
1085 "assert(23 in wheel_6.peg_positions)\n",
1086 "assert(10 in wheel_6.peg_positions)\n",
1087 "assert(wheel_6.position_l == 'c')"
1088 ]
1089 },
1090 {
1091 "cell_type": "code",
1092 "execution_count": 39,
1093 "metadata": {},
1094 "outputs": [
1095 {
1096 "data": {
1097 "text/plain": [
1098 "(0, 'c', [23, 10])"
1099 ]
1100 },
1101 "execution_count": 39,
1102 "metadata": {},
1103 "output_type": "execute_result"
1104 }
1105 ],
1106 "source": [
1107 "wheel_6.position, wheel_6.position_l, wheel_6.peg_positions"
1108 ]
1109 },
1110 {
1111 "cell_type": "code",
1112 "execution_count": 83,
1113 "metadata": {
1114 "collapsed": true
1115 },
1116 "outputs": [],
1117 "source": [
1118 "class Enigma(object):\n",
1119 " def __init__(self, reflector_spec,\n",
1120 " left_wheel_spec, left_wheel_pegs,\n",
1121 " middle_wheel_spec, middle_wheel_pegs,\n",
1122 " right_wheel_spec, right_wheel_pegs,\n",
1123 " left_ring_setting, middle_ring_setting, right_ring_setting,\n",
1124 " plugboard_setting):\n",
1125 " self.reflector = Reflector(reflector_spec)\n",
1126 " self.left_wheel = Wheel(left_wheel_spec, left_wheel_pegs, ring_setting=left_ring_setting)\n",
1127 " self.middle_wheel = Wheel(middle_wheel_spec, middle_wheel_pegs, ring_setting=middle_ring_setting)\n",
1128 " self.right_wheel = Wheel(right_wheel_spec, right_wheel_pegs, ring_setting=right_ring_setting)\n",
1129 " self.plugboard = Plugboard(plugboard_setting)\n",
1130 " \n",
1131 " def __getattribute__(self,name):\n",
1132 " if name=='wheel_positions':\n",
1133 " return self.left_wheel.position, self.middle_wheel.position, self.right_wheel.position \n",
1134 " elif name=='wheel_positions_l':\n",
1135 " return self.left_wheel.position_l, self.middle_wheel.position_l, self.right_wheel.position_l \n",
1136 " elif name=='peg_positions':\n",
1137 " return self.left_wheel.peg_positions, self.middle_wheel.peg_positions, self.right_wheel.peg_positions\n",
1138 " else:\n",
1139 " return object.__getattribute__(self, name)\n",
1140 "\n",
1141 " \n",
1142 " def set_wheels(self, left_wheel_position, middle_wheel_position, right_wheel_position):\n",
1143 " self.left_wheel.set_position(left_wheel_position)\n",
1144 " self.middle_wheel.set_position(middle_wheel_position)\n",
1145 " self.right_wheel.set_position(right_wheel_position)\n",
1146 " \n",
1147 " def lookup(self, letter):\n",
1148 " a = self.plugboard.forward(letter)\n",
1149 " b = self.right_wheel.forward(a)\n",
1150 " c = self.middle_wheel.forward(b)\n",
1151 " d = self.left_wheel.forward(c)\n",
1152 " e = self.reflector.forward(d)\n",
1153 " f = self.left_wheel.backward(e)\n",
1154 " g = self.middle_wheel.backward(f)\n",
1155 " h = self.right_wheel.backward(g)\n",
1156 " i = self.plugboard.backward(h)\n",
1157 " return i\n",
1158 " \n",
1159 " def advance(self):\n",
1160 " advance_middle = False\n",
1161 " advance_left = False\n",
1162 " if 0 in self.right_wheel.peg_positions:\n",
1163 " advance_middle = True\n",
1164 " if 0 in self.middle_wheel.peg_positions:\n",
1165 " advance_left = True\n",
1166 " advance_middle = True\n",
1167 " self.right_wheel.advance()\n",
1168 " if advance_middle: self.middle_wheel.advance()\n",
1169 " if advance_left: self.left_wheel.advance()\n",
1170 " \n",
1171 " def encipher_letter(self, letter):\n",
1172 " self.advance()\n",
1173 " return self.lookup(letter)\n",
1174 " \n",
1175 " def encipher(self, message, debug=False):\n",
1176 " enciphered = ''\n",
1177 " for letter in clean(message):\n",
1178 " enciphered += self.encipher_letter(letter)\n",
1179 " if debug:\n",
1180 " print('Wheels now', list(self.wheel_positions_l), 'enciphering {} -> {}'.format(letter, self.lookup(letter)))\n",
1181 " return enciphered"
1182 ]
1183 },
1184 {
1185 "cell_type": "code",
1186 "execution_count": 82,
1187 "metadata": {},
1188 "outputs": [
1189 {
1190 "data": {
1191 "text/plain": [
1192 "\"('a', 'b', 'c')\""
1193 ]
1194 },
1195 "execution_count": 82,
1196 "metadata": {},
1197 "output_type": "execute_result"
1198 }
1199 ],
1200 "source": [
1201 "sfsdf = ('a', 'b', 'c')\n",
1202 "str(sfsdf)"
1203 ]
1204 },
1205 {
1206 "cell_type": "code",
1207 "execution_count": 41,
1208 "metadata": {
1209 "collapsed": true
1210 },
1211 "outputs": [],
1212 "source": [
1213 "enigma = Enigma(reflector_b_spec, \n",
1214 " wheel_i_spec, wheel_i_pegs,\n",
1215 " wheel_ii_spec, wheel_ii_pegs,\n",
1216 " wheel_iii_spec, wheel_iii_pegs,\n",
1217 " 1, 1, 1,\n",
1218 " '')"
1219 ]
1220 },
1221 {
1222 "cell_type": "code",
1223 "execution_count": 42,
1224 "metadata": {},
1225 "outputs": [
1226 {
1227 "data": {
1228 "text/plain": [
1229 "'u'"
1230 ]
1231 },
1232 "execution_count": 42,
1233 "metadata": {},
1234 "output_type": "execute_result"
1235 }
1236 ],
1237 "source": [
1238 "enigma.lookup('a')"
1239 ]
1240 },
1241 {
1242 "cell_type": "code",
1243 "execution_count": 43,
1244 "metadata": {},
1245 "outputs": [
1246 {
1247 "data": {
1248 "text/plain": [
1249 "'a'"
1250 ]
1251 },
1252 "execution_count": 43,
1253 "metadata": {},
1254 "output_type": "execute_result"
1255 }
1256 ],
1257 "source": [
1258 "enigma.lookup('u')"
1259 ]
1260 },
1261 {
1262 "cell_type": "code",
1263 "execution_count": 44,
1264 "metadata": {},
1265 "outputs": [
1266 {
1267 "data": {
1268 "text/plain": [
1269 "'uejobtpzwcnsrkdgvmlfaqiyxh'"
1270 ]
1271 },
1272 "execution_count": 44,
1273 "metadata": {},
1274 "output_type": "execute_result"
1275 }
1276 ],
1277 "source": [
1278 "cat(enigma.lookup(l) for l in string.ascii_lowercase)"
1279 ]
1280 },
1281 {
1282 "cell_type": "code",
1283 "execution_count": 45,
1284 "metadata": {
1285 "scrolled": true
1286 },
1287 "outputs": [
1288 {
1289 "name": "stdout",
1290 "output_type": "stream",
1291 "text": [
1292 "0 :: a a a ; [16] [4] [21] uejobtpzwcnsrkdgvmlfaqiyxh\n",
1293 "1 :: a a b ; [16] [4] [20] baqmfexihswpdytlcvjozrkgnu\n",
1294 "2 :: a a c ; [16] [4] [19] djralkwpobfeyqihncxzvugsmt\n",
1295 "3 :: a a d ; [16] [4] [18] zlejcuitgdmbkonsvxphfqyrwa\n",
1296 "4 :: a a e ; [16] [4] [17] gcblwtakqzhdosmxiunfryepvj\n",
1297 "5 :: a a f ; [16] [4] [16] osnirgfmdpvuhcajwebxlkqtzy\n",
1298 "6 :: a a g ; [16] [4] [15] wymvnqzjlhoicekuftxrpdasbg\n",
1299 "7 :: a a h ; [16] [4] [14] cjafkdztpbeuormiwnvhlsqyxg\n",
1300 "8 :: a a i ; [16] [4] [13] xijuyslvbczgnmqwotfrdhpaek\n",
1301 "9 :: a a j ; [16] [4] [12] lfzrwbytjisaovmuxdkhpneqgc\n",
1302 "10 :: a a k ; [16] [4] [11] tkezcqynuwbpvhslfxoaimjrgd\n",
1303 "11 :: a a l ; [16] [4] [10] kiwfnduxbsaotelqpvjmgrchzy\n",
1304 "12 :: a a m ; [16] [4] [9] sfkutbpoxycrnmhgwlaedzqijv\n",
1305 "13 :: a a n ; [16] [4] [8] baqwlkhgrsfextpocijnvudmzy\n",
1306 "14 :: a a o ; [16] [4] [7] teofbdzxqkjyrscvimnawpuhlg\n",
1307 "15 :: a a p ; [16] [4] [6] mhypswrbzxqvaondkgeutlfjci\n",
1308 "16 :: a a q ; [16] [4] [5] cpasnrhgkuixzevbyfdwjotlqm\n",
1309 "17 :: a a r ; [16] [4] [4] dlfatcjwygvbnmzrxpueskhqio\n",
1310 "18 :: a a s ; [16] [4] [3] lxymzjuqtfpadsrkhonigwvbce\n",
1311 "19 :: a a t ; [16] [4] [2] puvioztjdhxmlyeawsrgbcqknf\n",
1312 "20 :: a a u ; [16] [4] [1] baigpldqcowfyzjehvtsxrkumn\n",
1313 "21 :: a a v ; [16] [4] [0] mnvfydiwgzsoablrxpkutchqej\n",
1314 "22 :: a b w ; [16] [3] [25] ulfopcykswhbzvderqixanjtgm\n",
1315 "23 :: a b x ; [16] [3] [24] qmwftdyovursbzhxaklejicpgn\n",
1316 "24 :: a b y ; [16] [3] [23] oljmzxrvucybdqasngpwihtfke\n",
1317 "25 :: a b z ; [16] [3] [22] fwevcalzxutgysrqponkjdbimh\n"
1318 ]
1319 }
1320 ],
1321 "source": [
1322 "enigma.set_wheels('a', 'a', 'a')\n",
1323 "for i in range(26):\n",
1324 " print(i, '::', \n",
1325 " enigma.left_wheel.position_l, enigma.middle_wheel.position_l, enigma.right_wheel.position_l, ';',\n",
1326 " enigma.left_wheel.peg_positions, enigma.middle_wheel.peg_positions, enigma.right_wheel.peg_positions, \n",
1327 " cat(enigma.lookup(l) for l in string.ascii_lowercase))\n",
1328 " enigma.advance()"
1329 ]
1330 },
1331 {
1332 "cell_type": "code",
1333 "execution_count": 46,
1334 "metadata": {
1335 "collapsed": true,
1336 "scrolled": true
1337 },
1338 "outputs": [],
1339 "source": [
1340 "enigma.set_wheels('a', 'a', 't')\n",
1341 "assert(enigma.wheel_positions == (0, 0, 19))\n",
1342 "assert(cat(enigma.wheel_positions_l) == 'aat')\n",
1343 "assert(enigma.peg_positions == ([16], [4], [2]))\n",
1344 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'puvioztjdhxmlyeawsrgbcqknf')\n",
1345 "\n",
1346 "enigma.advance()\n",
1347 "assert(enigma.wheel_positions == (0, 0, 20))\n",
1348 "assert(cat(enigma.wheel_positions_l) == 'aau')\n",
1349 "assert(enigma.peg_positions == ([16], [4], [1]))\n",
1350 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'baigpldqcowfyzjehvtsxrkumn')\n",
1351 "\n",
1352 "enigma.advance()\n",
1353 "assert(enigma.wheel_positions == (0, 0, 21))\n",
1354 "assert(cat(enigma.wheel_positions_l) == 'aav')\n",
1355 "assert(enigma.peg_positions == ([16], [4], [0]))\n",
1356 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mnvfydiwgzsoablrxpkutchqej')\n",
1357 "\n",
1358 "enigma.advance()\n",
1359 "assert(enigma.wheel_positions == (0, 1, 22))\n",
1360 "assert(cat(enigma.wheel_positions_l) == 'abw')\n",
1361 "assert(enigma.peg_positions == ([16], [3], [25]))\n",
1362 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ulfopcykswhbzvderqixanjtgm')\n",
1363 "\n",
1364 "enigma.advance()\n",
1365 "assert(enigma.wheel_positions == (0, 1, 23))\n",
1366 "assert(cat(enigma.wheel_positions_l) == 'abx')\n",
1367 "assert(enigma.peg_positions == ([16], [3], [24]))\n",
1368 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qmwftdyovursbzhxaklejicpgn')\n",
1369 "\n",
1370 "enigma.advance()\n",
1371 "assert(enigma.wheel_positions == (0, 1, 24))\n",
1372 "assert(cat(enigma.wheel_positions_l) == 'aby')\n",
1373 "assert(enigma.peg_positions == ([16], [3], [23]))\n",
1374 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'oljmzxrvucybdqasngpwihtfke')\n"
1375 ]
1376 },
1377 {
1378 "cell_type": "code",
1379 "execution_count": 47,
1380 "metadata": {
1381 "scrolled": true
1382 },
1383 "outputs": [
1384 {
1385 "name": "stdout",
1386 "output_type": "stream",
1387 "text": [
1388 "(1, 5, 24) ('b', 'f', 'y') ([15], [25], [23]) baknstqzrmcxjdvygiefwoulph\n"
1389 ]
1390 }
1391 ],
1392 "source": [
1393 "enigma.set_wheels('a', 'd', 't')\n",
1394 "assert(enigma.wheel_positions == (0, 3, 19))\n",
1395 "assert(cat(enigma.wheel_positions_l) == 'adt')\n",
1396 "assert(enigma.peg_positions == ([16], [1], [2]))\n",
1397 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'zcbpqxwsjiuonmldethrkygfva')\n",
1398 "\n",
1399 "enigma.advance()\n",
1400 "assert(enigma.wheel_positions == (0, 3, 20))\n",
1401 "assert(cat(enigma.wheel_positions_l) == 'adu')\n",
1402 "assert(enigma.peg_positions == ([16], [1], [1]))\n",
1403 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ehprawjbngotxikcsdqlzyfmvu')\n",
1404 "\n",
1405 "enigma.advance()\n",
1406 "assert(enigma.wheel_positions == (0, 3, 21))\n",
1407 "assert(cat(enigma.wheel_positions_l) == 'adv')\n",
1408 "assert(enigma.peg_positions == ([16], [1], [0]))\n",
1409 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'eqzxarpihmnvjkwgbfuyslodtc')\n",
1410 "\n",
1411 "enigma.advance()\n",
1412 "assert(enigma.wheel_positions == (0, 4, 22))\n",
1413 "assert(cat(enigma.wheel_positions_l) == 'aew')\n",
1414 "assert(enigma.peg_positions == ([16], [0], [25]))\n",
1415 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qedcbtpluzmhkongavwfirsyxj')\n",
1416 "\n",
1417 "enigma.advance()\n",
1418 "assert(enigma.wheel_positions == (1, 5, 23))\n",
1419 "assert(cat(enigma.wheel_positions_l) == 'bfx')\n",
1420 "assert(enigma.peg_positions == ([15], [25], [24]))\n",
1421 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'iwuedhsfazqxytvrkpgncoblmj')\n",
1422 "\n",
1423 "enigma.advance()\n",
1424 "assert(enigma.wheel_positions == (1, 5, 24))\n",
1425 "assert(cat(enigma.wheel_positions_l) == 'bfy')\n",
1426 "assert(enigma.peg_positions == ([15], [25], [23]))\n",
1427 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'baknstqzrmcxjdvygiefwoulph')\n",
1428 "\n",
1429 "print(enigma.wheel_positions, enigma.wheel_positions_l, enigma.peg_positions, \n",
1430 " cat(enigma.lookup(l) for l in string.ascii_lowercase))\n"
1431 ]
1432 },
1433 {
1434 "cell_type": "code",
1435 "execution_count": 48,
1436 "metadata": {},
1437 "outputs": [
1438 {
1439 "data": {
1440 "text/plain": [
1441 "'olpfhnvflyn'"
1442 ]
1443 },
1444 "execution_count": 48,
1445 "metadata": {},
1446 "output_type": "execute_result"
1447 }
1448 ],
1449 "source": [
1450 "enigma.set_wheels('a', 'a', 'a')\n",
1451 "ct = enigma.encipher('testmessage')\n",
1452 "assert(ct == 'olpfhnvflyn')\n",
1453 "ct"
1454 ]
1455 },
1456 {
1457 "cell_type": "code",
1458 "execution_count": 49,
1459 "metadata": {},
1460 "outputs": [
1461 {
1462 "data": {
1463 "text/plain": [
1464 "'lawnjgpwjik'"
1465 ]
1466 },
1467 "execution_count": 49,
1468 "metadata": {},
1469 "output_type": "execute_result"
1470 }
1471 ],
1472 "source": [
1473 "enigma.set_wheels('a', 'd', 't')\n",
1474 "ct = enigma.encipher('testmessage')\n",
1475 "assert(ct == 'lawnjgpwjik')\n",
1476 "ct"
1477 ]
1478 },
1479 {
1480 "cell_type": "code",
1481 "execution_count": 50,
1482 "metadata": {},
1483 "outputs": [
1484 {
1485 "name": "stdout",
1486 "output_type": "stream",
1487 "text": [
1488 "enigma.advance()\n",
1489 "assert(enigma.wheel_positions == (1, 5, 5))\n",
1490 "assert(cat(enigma.wheel_positions_l) == 'bff')\n",
1491 "assert(enigma.peg_positions == ([15], [25], [16]))\n",
1492 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'zpqiogfsdlmjkyebcvhxwrutna')\n",
1493 "\n",
1494 "enigma.advance()\n",
1495 "assert(enigma.wheel_positions == (1, 5, 6))\n",
1496 "assert(cat(enigma.wheel_positions_l) == 'bfg')\n",
1497 "assert(enigma.peg_positions == ([15], [25], [15]))\n",
1498 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'fjmnwayslbxicdpouthrqzekgv')\n",
1499 "\n",
1500 "enigma.advance()\n",
1501 "assert(enigma.wheel_positions == (1, 5, 7))\n",
1502 "assert(cat(enigma.wheel_positions_l) == 'bfh')\n",
1503 "assert(enigma.peg_positions == ([15], [25], [14]))\n",
1504 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'csafzdyloxuhnmitwvbpkrqjge')\n",
1505 "\n",
1506 "enigma.advance()\n",
1507 "assert(enigma.wheel_positions == (1, 5, 8))\n",
1508 "assert(cat(enigma.wheel_positions_l) == 'bfi')\n",
1509 "assert(enigma.peg_positions == ([15], [25], [13]))\n",
1510 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'kihyvulcbtagwrqzonxjfemsdp')\n",
1511 "\n",
1512 "enigma.advance()\n",
1513 "assert(enigma.wheel_positions == (1, 5, 9))\n",
1514 "assert(cat(enigma.wheel_positions_l) == 'bfj')\n",
1515 "assert(enigma.peg_positions == ([15], [25], [12]))\n",
1516 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pgzrytbksqhwxvuajdifonlmec')\n",
1517 "\n",
1518 "enigma.advance()\n",
1519 "assert(enigma.wheel_positions == (1, 5, 10))\n",
1520 "assert(cat(enigma.wheel_positions_l) == 'bfk')\n",
1521 "assert(enigma.peg_positions == ([15], [25], [11]))\n",
1522 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'fkirsazncwbvyhpoudexqljtmg')\n",
1523 "\n",
1524 "enigma.advance()\n",
1525 "assert(enigma.wheel_positions == (1, 5, 11))\n",
1526 "assert(cat(enigma.wheel_positions_l) == 'bfl')\n",
1527 "assert(enigma.peg_positions == ([15], [25], [10]))\n",
1528 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mhkronubsvctafeqpdilgjxwzy')\n",
1529 "\n",
1530 "enigma.advance()\n",
1531 "assert(enigma.wheel_positions == (1, 5, 12))\n",
1532 "assert(cat(enigma.wheel_positions_l) == 'bfm')\n",
1533 "assert(enigma.peg_positions == ([15], [25], [9]))\n",
1534 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'gnkuoxarzycmlbetvhwpdqsfji')\n",
1535 "\n",
1536 "enigma.advance()\n",
1537 "assert(enigma.wheel_positions == (1, 5, 13))\n",
1538 "assert(cat(enigma.wheel_positions_l) == 'bfn')\n",
1539 "assert(enigma.peg_positions == ([15], [25], [8]))\n",
1540 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'bainslqkcxhfudpogtermwvjzy')\n",
1541 "\n",
1542 "enigma.advance()\n",
1543 "assert(enigma.wheel_positions == (1, 5, 14))\n",
1544 "assert(cat(enigma.wheel_positions_l) == 'bfo')\n",
1545 "assert(enigma.peg_positions == ([15], [25], [7]))\n",
1546 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xemfbdnwjitycgzusvqkprhalo')\n",
1547 "\n",
1548 "enigma.advance()\n",
1549 "assert(enigma.wheel_positions == (1, 5, 15))\n",
1550 "assert(cat(enigma.wheel_positions_l) == 'bfp')\n",
1551 "assert(enigma.peg_positions == ([15], [25], [6]))\n",
1552 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qixksmhgbtdvfonrapejwluczy')\n",
1553 "\n",
1554 "enigma.advance()\n",
1555 "assert(enigma.wheel_positions == (1, 5, 16))\n",
1556 "assert(cat(enigma.wheel_positions_l) == 'bfq')\n",
1557 "assert(enigma.peg_positions == ([15], [25], [5]))\n",
1558 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cgaulmbskwiefrtzynhodxjvqp')\n",
1559 "\n",
1560 "enigma.advance()\n",
1561 "assert(enigma.wheel_positions == (1, 5, 17))\n",
1562 "assert(cat(enigma.wheel_positions_l) == 'bfr')\n",
1563 "assert(enigma.peg_positions == ([15], [25], [4]))\n",
1564 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'iwqfldszaxvenmyrcpgutkbjoh')\n",
1565 "\n",
1566 "enigma.advance()\n",
1567 "assert(enigma.wheel_positions == (1, 5, 18))\n",
1568 "assert(cat(enigma.wheel_positions_l) == 'bfs')\n",
1569 "assert(enigma.peg_positions == ([15], [25], [3]))\n",
1570 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'vxykrjilgfdhqtusmepnoazbcw')\n",
1571 "\n",
1572 "enigma.advance()\n",
1573 "assert(enigma.wheel_positions == (1, 5, 19))\n",
1574 "assert(cat(enigma.wheel_positions_l) == 'bft')\n",
1575 "assert(enigma.peg_positions == ([15], [25], [2]))\n",
1576 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ieysbvkjahgmlpxnwtdrzfqocu')\n",
1577 "\n",
1578 "enigma.advance()\n",
1579 "assert(enigma.wheel_positions == (1, 5, 20))\n",
1580 "assert(cat(enigma.wheel_positions_l) == 'bfu')\n",
1581 "assert(enigma.peg_positions == ([15], [25], [1]))\n",
1582 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'baihkjvdcfepywsltxoqzgnrmu')\n",
1583 "\n",
1584 "enigma.advance()\n",
1585 "assert(enigma.wheel_positions == (1, 5, 21))\n",
1586 "assert(cat(enigma.wheel_positions_l) == 'bfv')\n",
1587 "assert(enigma.peg_positions == ([15], [25], [0]))\n",
1588 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'bayjtrilgdshvzuwxfkeompqcn')\n",
1589 "\n",
1590 "enigma.advance()\n",
1591 "assert(enigma.wheel_positions == (1, 6, 22))\n",
1592 "assert(cat(enigma.wheel_positions_l) == 'bgw')\n",
1593 "assert(enigma.peg_positions == ([15], [24], [25]))\n",
1594 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'rszqohpfxyutvwegdablkmnijc')\n",
1595 "\n",
1596 "enigma.advance()\n",
1597 "assert(enigma.wheel_positions == (1, 6, 23))\n",
1598 "assert(cat(enigma.wheel_positions_l) == 'bgx')\n",
1599 "assert(enigma.peg_positions == ([15], [24], [24]))\n",
1600 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nfoxhbzeyrwqpacmljtsvukdig')\n",
1601 "\n",
1602 "enigma.advance()\n",
1603 "assert(enigma.wheel_positions == (1, 6, 24))\n",
1604 "assert(cat(enigma.wheel_positions_l) == 'bgy')\n",
1605 "assert(enigma.peg_positions == ([15], [24], [23]))\n",
1606 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'czaogmeihtuqfsdxlwnjkyrpvb')\n",
1607 "\n",
1608 "enigma.advance()\n",
1609 "assert(enigma.wheel_positions == (1, 6, 25))\n",
1610 "assert(cat(enigma.wheel_positions_l) == 'bgz')\n",
1611 "assert(enigma.peg_positions == ([15], [24], [22]))\n",
1612 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'omwgysdjkhizbxarupfvqtcnel')\n",
1613 "\n",
1614 "enigma.advance()\n",
1615 "assert(enigma.wheel_positions == (1, 6, 0))\n",
1616 "assert(cat(enigma.wheel_positions_l) == 'bga')\n",
1617 "assert(enigma.peg_positions == ([15], [24], [21]))\n",
1618 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cxafmdrzoqutepinjgvlksybwh')\n",
1619 "\n",
1620 "enigma.advance()\n",
1621 "assert(enigma.wheel_positions == (1, 6, 1))\n",
1622 "assert(cat(enigma.wheel_positions_l) == 'bgb')\n",
1623 "assert(enigma.peg_positions == ([15], [24], [20]))\n",
1624 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'jymvnrxkoahwceiuzftspdlgbq')\n",
1625 "\n",
1626 "enigma.advance()\n",
1627 "assert(enigma.wheel_positions == (1, 6, 2))\n",
1628 "assert(cat(enigma.wheel_positions_l) == 'bgc')\n",
1629 "assert(enigma.peg_positions == ([15], [24], [19]))\n",
1630 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'uzlyiqwrestcnmxvfhjkapgodb')\n",
1631 "\n",
1632 "enigma.advance()\n",
1633 "assert(enigma.wheel_positions == (1, 6, 3))\n",
1634 "assert(cat(enigma.wheel_positions_l) == 'bgd')\n",
1635 "assert(enigma.peg_positions == ([15], [24], [18]))\n",
1636 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'veosbuhgpzqynmcikwdxfartlj')\n",
1637 "\n",
1638 "enigma.advance()\n",
1639 "assert(enigma.wheel_positions == (1, 6, 4))\n",
1640 "assert(cat(enigma.wheel_positions_l) == 'bge')\n",
1641 "assert(enigma.peg_positions == ([15], [24], [17]))\n",
1642 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ydhbmtrclxsiezpougkfqwvjan')\n",
1643 "\n"
1644 ]
1645 }
1646 ],
1647 "source": [
1648 "\n",
1649 "for i in range(26):\n",
1650 " enigma.advance()\n",
1651 " print('enigma.advance()')\n",
1652 " print(\"assert(enigma.wheel_positions == {})\".format(enigma.wheel_positions))\n",
1653 " print(\"assert(cat(enigma.wheel_positions_l) == '{}')\".format(cat(enigma.wheel_positions_l)))\n",
1654 " print(\"assert(enigma.peg_positions == {})\".format(enigma.peg_positions))\n",
1655 " print(\"assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == '{}')\".format(cat(enigma.lookup(l) for l in string.ascii_lowercase)))\n",
1656 " print()"
1657 ]
1658 },
1659 {
1660 "cell_type": "code",
1661 "execution_count": 51,
1662 "metadata": {},
1663 "outputs": [
1664 {
1665 "data": {
1666 "text/plain": [
1667 "'bahxvfrpdc'"
1668 ]
1669 },
1670 "execution_count": 51,
1671 "metadata": {},
1672 "output_type": "execute_result"
1673 }
1674 ],
1675 "source": [
1676 "enigma.set_wheels('a', 'd', 't')\n",
1677 "ct = enigma.encipher('hellothere')\n",
1678 "assert(ct == 'bahxvfrpdc')\n",
1679 "ct"
1680 ]
1681 },
1682 {
1683 "cell_type": "code",
1684 "execution_count": 52,
1685 "metadata": {},
1686 "outputs": [
1687 {
1688 "data": {
1689 "text/plain": [
1690 "'kvmmwrlqlqsqpeugjrcxzwpfyiyybwloewrouvkpoztceuwtfjzqwpbqldttsr'"
1691 ]
1692 },
1693 "execution_count": 52,
1694 "metadata": {},
1695 "output_type": "execute_result"
1696 }
1697 ],
1698 "source": [
1699 "enigma.set_wheels('b', 'd', 'q')\n",
1700 "ct = enigma.encipher('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')\n",
1701 "assert(ct == 'kvmmwrlqlqsqpeugjrcxzwpfyiyybwloewrouvkpoztceuwtfjzqwpbqldttsr')\n",
1702 "assert(enigma.left_wheel.position_l == 'c')\n",
1703 "assert(enigma.middle_wheel.position_l == 'h')\n",
1704 "assert(enigma.right_wheel.position_l == 'a')\n",
1705 "ct"
1706 ]
1707 },
1708 {
1709 "cell_type": "code",
1710 "execution_count": 53,
1711 "metadata": {},
1712 "outputs": [
1713 {
1714 "data": {
1715 "text/plain": [
1716 "'c'"
1717 ]
1718 },
1719 "execution_count": 53,
1720 "metadata": {},
1721 "output_type": "execute_result"
1722 }
1723 ],
1724 "source": [
1725 "enigma.left_wheel.position_l"
1726 ]
1727 },
1728 {
1729 "cell_type": "code",
1730 "execution_count": 54,
1731 "metadata": {
1732 "collapsed": true
1733 },
1734 "outputs": [],
1735 "source": [
1736 "# Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm\n",
1737 "# Enigma simulation settings are \n",
1738 "# http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJFE;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX\n",
1739 "w_enigma = Enigma(reflector_b_spec, \n",
1740 " wheel_i_spec, wheel_i_pegs,\n",
1741 " wheel_v_spec, wheel_v_pegs,\n",
1742 " wheel_iii_spec, wheel_iii_pegs,\n",
1743 " 6, 20, 24,\n",
1744 " 'ua pf rq so ni ey bg hl tx zj')"
1745 ]
1746 },
1747 {
1748 "cell_type": "code",
1749 "execution_count": 55,
1750 "metadata": {
1751 "collapsed": true
1752 },
1753 "outputs": [],
1754 "source": [
1755 "# Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm\n",
1756 "# Enigma simulation settings are \n",
1757 "# http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJFE;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX\n",
1758 "enigma = Enigma(reflector_b_spec, \n",
1759 " wheel_i_spec, wheel_i_pegs,\n",
1760 " wheel_v_spec, wheel_v_pegs,\n",
1761 " wheel_iii_spec, wheel_iii_pegs,\n",
1762 " 6, 20, 24,\n",
1763 " 'ua pf rq so ni ey bg hl tx zj')"
1764 ]
1765 },
1766 {
1767 "cell_type": "code",
1768 "execution_count": 56,
1769 "metadata": {
1770 "collapsed": true
1771 },
1772 "outputs": [],
1773 "source": [
1774 "enigma.set_wheels('j', 'e', 'u')\n",
1775 "\n",
1776 "enigma.advance()\n",
1777 "assert(enigma.wheel_positions == (4, 11, 24))\n",
1778 "assert(cat(enigma.wheel_positions_l) == 'jev')\n",
1779 "assert(enigma.peg_positions == ([7], [21], [0]))\n",
1780 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mvqjlyowkdieasgzcunxrbhtfp')\n",
1781 "\n",
1782 "enigma.advance()\n",
1783 "assert(enigma.wheel_positions == (4, 12, 25))\n",
1784 "assert(cat(enigma.wheel_positions_l) == 'jfw')\n",
1785 "assert(enigma.peg_positions == ([7], [20], [25]))\n",
1786 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'sjolzuyvrbwdpxcmtiaqfhknge')\n",
1787 "\n",
1788 "enigma.advance()\n",
1789 "assert(enigma.wheel_positions == (4, 12, 0))\n",
1790 "assert(cat(enigma.wheel_positions_l) == 'jfx')\n",
1791 "assert(enigma.peg_positions == ([7], [20], [24]))\n",
1792 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qrxedkoywufmlvgsabpzjnicht')\n",
1793 "\n",
1794 "enigma.advance()\n",
1795 "assert(enigma.wheel_positions == (4, 12, 1))\n",
1796 "assert(cat(enigma.wheel_positions_l) == 'jfy')\n",
1797 "assert(enigma.peg_positions == ([7], [20], [23]))\n",
1798 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hpsukliagqefwvtbjxcodnmrzy')\n",
1799 "\n",
1800 "enigma.advance()\n",
1801 "assert(enigma.wheel_positions == (4, 12, 2))\n",
1802 "assert(cat(enigma.wheel_positions_l) == 'jfz')\n",
1803 "assert(enigma.peg_positions == ([7], [20], [22]))\n",
1804 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'zevnbpyqowrtxdifhkulscjmga')\n"
1805 ]
1806 },
1807 {
1808 "cell_type": "code",
1809 "execution_count": 57,
1810 "metadata": {
1811 "collapsed": true
1812 },
1813 "outputs": [],
1814 "source": [
1815 "enigma.set_wheels('i', 'd', 'z')\n",
1816 "\n",
1817 "enigma.advance()\n",
1818 "assert(enigma.wheel_positions == (3, 10, 3))\n",
1819 "assert(cat(enigma.wheel_positions_l) == 'ida')\n",
1820 "assert(enigma.peg_positions == ([8], [22], [21]))\n",
1821 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ikhpqrvcambzjondefwyxgsutl')\n",
1822 "\n",
1823 "enigma.advance()\n",
1824 "assert(enigma.wheel_positions == (3, 10, 4))\n",
1825 "assert(cat(enigma.wheel_positions_l) == 'idb')\n",
1826 "assert(enigma.peg_positions == ([8], [22], [20]))\n",
1827 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cdabskhgzwfmlqvunyexpojtri')\n",
1828 "\n",
1829 "enigma.advance()\n",
1830 "assert(enigma.wheel_positions == (3, 10, 5))\n",
1831 "assert(cat(enigma.wheel_positions_l) == 'idc')\n",
1832 "assert(enigma.peg_positions == ([8], [22], [19]))\n",
1833 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pcbwiqhgemyvjsuaftnroldzkx')\n",
1834 "\n",
1835 "enigma.advance()\n",
1836 "assert(enigma.wheel_positions == (3, 10, 6))\n",
1837 "assert(cat(enigma.wheel_positions_l) == 'idd')\n",
1838 "assert(enigma.peg_positions == ([8], [22], [18]))\n",
1839 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xcbfvdnouptmlghjzwykierasq')\n",
1840 "\n",
1841 "enigma.advance()\n",
1842 "assert(enigma.wheel_positions == (3, 10, 7))\n",
1843 "assert(cat(enigma.wheel_positions_l) == 'ide')\n",
1844 "assert(enigma.peg_positions == ([8], [22], [17]))\n",
1845 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xfvglbdynuseriwqpmkzjcoaht')\n",
1846 "\n",
1847 "enigma.advance()\n",
1848 "assert(enigma.wheel_positions == (3, 10, 8))\n",
1849 "assert(cat(enigma.wheel_positions_l) == 'idf')\n",
1850 "assert(enigma.peg_positions == ([8], [22], [16]))\n",
1851 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'tfpqlbouynsewjgcdxkahzmriv')\n",
1852 "\n",
1853 "enigma.advance()\n",
1854 "assert(enigma.wheel_positions == (3, 10, 9))\n",
1855 "assert(cat(enigma.wheel_positions_l) == 'idg')\n",
1856 "assert(enigma.peg_positions == ([8], [22], [15]))\n",
1857 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cjaunvlwtbygzexrspqidfhokm')\n",
1858 "\n",
1859 "enigma.advance()\n",
1860 "assert(enigma.wheel_positions == (3, 10, 10))\n",
1861 "assert(cat(enigma.wheel_positions_l) == 'idh')\n",
1862 "assert(enigma.peg_positions == ([8], [22], [14]))\n",
1863 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'yltxkrqvowebzpingfucshjdam')\n",
1864 "\n",
1865 "enigma.advance()\n",
1866 "assert(enigma.wheel_positions == (3, 10, 11))\n",
1867 "assert(cat(enigma.wheel_positions_l) == 'idi')\n",
1868 "assert(enigma.peg_positions == ([8], [22], [13]))\n",
1869 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'myktluzrnxceaiqsohpdfwvjbg')\n",
1870 "\n",
1871 "enigma.advance()\n",
1872 "assert(enigma.wheel_positions == (3, 10, 12))\n",
1873 "assert(cat(enigma.wheel_positions_l) == 'idj')\n",
1874 "assert(enigma.peg_positions == ([8], [22], [12]))\n",
1875 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pynjrmiugdqxfcvakewzhoslbt')\n",
1876 "\n",
1877 "enigma.advance()\n",
1878 "assert(enigma.wheel_positions == (3, 10, 13))\n",
1879 "assert(cat(enigma.wheel_positions_l) == 'idk')\n",
1880 "assert(enigma.peg_positions == ([8], [22], [11]))\n",
1881 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mwvedyplnoxhaijgrqtszcbkfu')\n",
1882 "\n",
1883 "enigma.advance()\n",
1884 "assert(enigma.wheel_positions == (3, 10, 14))\n",
1885 "assert(cat(enigma.wheel_positions_l) == 'idl')\n",
1886 "assert(enigma.peg_positions == ([8], [22], [10]))\n",
1887 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qcbrfeutvoxpnmjladzhgiykws')\n",
1888 "\n",
1889 "enigma.advance()\n",
1890 "assert(enigma.wheel_positions == (3, 10, 15))\n",
1891 "assert(cat(enigma.wheel_positions_l) == 'idm')\n",
1892 "assert(enigma.peg_positions == ([8], [22], [9]))\n",
1893 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'dnoahryetsmukbcvwfjilpqzgx')\n",
1894 "\n",
1895 "enigma.advance()\n",
1896 "assert(enigma.wheel_positions == (3, 10, 16))\n",
1897 "assert(cat(enigma.wheel_positions_l) == 'idn')\n",
1898 "assert(enigma.peg_positions == ([8], [22], [8]))\n",
1899 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nidcfehgbqsovalyjzkxwmutpr')\n",
1900 "\n",
1901 "enigma.advance()\n",
1902 "assert(enigma.wheel_positions == (3, 10, 17))\n",
1903 "assert(cat(enigma.wheel_positions_l) == 'ido')\n",
1904 "assert(enigma.peg_positions == ([8], [22], [7]))\n",
1905 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'joifxdulcarhzpbntkwqgysevm')\n",
1906 "\n",
1907 "enigma.advance()\n",
1908 "assert(enigma.wheel_positions == (3, 10, 18))\n",
1909 "assert(cat(enigma.wheel_positions_l) == 'idp')\n",
1910 "assert(enigma.peg_positions == ([8], [22], [6]))\n",
1911 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ptnlsxvozmwdjchayuebrgkfqi')\n",
1912 "\n",
1913 "enigma.advance()\n",
1914 "assert(enigma.wheel_positions == (3, 10, 19))\n",
1915 "assert(cat(enigma.wheel_positions_l) == 'idq')\n",
1916 "assert(enigma.peg_positions == ([8], [22], [5]))\n",
1917 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'slwopzqnmxybihdeguavrtcjkf')\n",
1918 "\n",
1919 "enigma.advance()\n",
1920 "assert(enigma.wheel_positions == (3, 10, 20))\n",
1921 "assert(cat(enigma.wheel_positions_l) == 'idr')\n",
1922 "assert(enigma.peg_positions == ([8], [22], [4]))\n",
1923 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hcbedwlamzogixkytsrqvufnpj')\n",
1924 "\n",
1925 "enigma.advance()\n",
1926 "assert(enigma.wheel_positions == (3, 10, 21))\n",
1927 "assert(cat(enigma.wheel_positions_l) == 'ids')\n",
1928 "assert(enigma.peg_positions == ([8], [22], [3]))\n",
1929 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'odxbjwzrmelkisavuhnyqpfctg')\n",
1930 "\n",
1931 "enigma.advance()\n",
1932 "assert(enigma.wheel_positions == (3, 10, 22))\n",
1933 "assert(cat(enigma.wheel_positions_l) == 'idt')\n",
1934 "assert(enigma.peg_positions == ([8], [22], [2]))\n",
1935 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'udgbfeclrwnhxksvtioqapjmzy')\n",
1936 "\n",
1937 "enigma.advance()\n",
1938 "assert(enigma.wheel_positions == (3, 10, 23))\n",
1939 "assert(cat(enigma.wheel_positions_l) == 'idu')\n",
1940 "assert(enigma.peg_positions == ([8], [22], [1]))\n",
1941 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nrdczqxmowvshaiufblypkjgte')\n",
1942 "\n",
1943 "enigma.advance()\n",
1944 "assert(enigma.wheel_positions == (3, 10, 24))\n",
1945 "assert(cat(enigma.wheel_positions_l) == 'idv')\n",
1946 "assert(enigma.peg_positions == ([8], [22], [0]))\n",
1947 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hkifjdoacebqtzgulyvmpsxwrn')\n",
1948 "\n",
1949 "enigma.advance()\n",
1950 "assert(enigma.wheel_positions == (3, 11, 25))\n",
1951 "assert(cat(enigma.wheel_positions_l) == 'iew')\n",
1952 "assert(enigma.peg_positions == ([8], [21], [25]))\n",
1953 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'yptzuhofqvnmlkgbixwcejsrad')\n",
1954 "\n",
1955 "enigma.advance()\n",
1956 "assert(enigma.wheel_positions == (3, 11, 0))\n",
1957 "assert(cat(enigma.wheel_positions_l) == 'iex')\n",
1958 "assert(enigma.peg_positions == ([8], [21], [24]))\n",
1959 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'vkdcwhqfjibzsptngumoraeyxl')\n",
1960 "\n",
1961 "enigma.advance()\n",
1962 "assert(enigma.wheel_positions == (3, 11, 1))\n",
1963 "assert(cat(enigma.wheel_positions_l) == 'iey')\n",
1964 "assert(enigma.peg_positions == ([8], [21], [23]))\n",
1965 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'wenpbqrouxlkychdfgzvitajms')\n"
1966 ]
1967 },
1968 {
1969 "cell_type": "code",
1970 "execution_count": 58,
1971 "metadata": {},
1972 "outputs": [
1973 {
1974 "data": {
1975 "text/plain": [
1976 "('verylongtestmessagewithanextrabitofmessageforgoodmeasure',\n",
1977 " (3, 12, 6),\n",
1978 " ('i', 'f', 'd'),\n",
1979 " ([8], [20], [18]),\n",
1980 " 'urygzpdmxtwshqvfnbljaokice')"
1981 ]
1982 },
1983 "execution_count": 58,
1984 "metadata": {},
1985 "output_type": "execute_result"
1986 }
1987 ],
1988 "source": [
1989 "enigma.set_wheels('i', 'd', 'z')\n",
1990 "ct = enigma.encipher('verylongtestmessagewithanextrabitofmessageforgoodmeasure')\n",
1991 "assert(ct == 'gstsegeqdrthkfwesljjomfvcqwcfspxpfqqmewvddybarzwubxtpejz')\n",
1992 "assert(enigma.wheel_positions == (3, 12, 6))\n",
1993 "assert(cat(enigma.wheel_positions_l) == 'ifd')\n",
1994 "assert(enigma.peg_positions == ([8], [20], [18]))\n",
1995 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'urygzpdmxtwshqvfnbljaokice')\n",
1996 "\n",
1997 "enigma.set_wheels('i', 'd', 'z')\n",
1998 "pt = enigma.encipher('gstsegeqdrthkfwesljjomfvcqwcfspxpfqqmewvddybarzwubxtpejz')\n",
1999 "assert(pt == 'verylongtestmessagewithanextrabitofmessageforgoodmeasure')\n",
2000 "\n",
2001 "pt, enigma.wheel_positions, enigma.wheel_positions_l, enigma.peg_positions, cat(enigma.lookup(l) for l in string.ascii_lowercase)"
2002 ]
2003 },
2004 {
2005 "cell_type": "code",
2006 "execution_count": 59,
2007 "metadata": {},
2008 "outputs": [
2009 {
2010 "name": "stdout",
2011 "output_type": "stream",
2012 "text": [
2013 "enigma.advance()\n",
2014 "assert(enigma.wheel_positions == (3, 10, 3))\n",
2015 "assert(cat(enigma.wheel_positions_l) == 'ida')\n",
2016 "assert(enigma.peg_positions == ([8], [22], [21]))\n",
2017 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ikhpqrvcambzjondefwyxgsutl')\n",
2018 "\n",
2019 "enigma.advance()\n",
2020 "assert(enigma.wheel_positions == (3, 10, 4))\n",
2021 "assert(cat(enigma.wheel_positions_l) == 'idb')\n",
2022 "assert(enigma.peg_positions == ([8], [22], [20]))\n",
2023 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cdabskhgzwfmlqvunyexpojtri')\n",
2024 "\n",
2025 "enigma.advance()\n",
2026 "assert(enigma.wheel_positions == (3, 10, 5))\n",
2027 "assert(cat(enigma.wheel_positions_l) == 'idc')\n",
2028 "assert(enigma.peg_positions == ([8], [22], [19]))\n",
2029 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pcbwiqhgemyvjsuaftnroldzkx')\n",
2030 "\n",
2031 "enigma.advance()\n",
2032 "assert(enigma.wheel_positions == (3, 10, 6))\n",
2033 "assert(cat(enigma.wheel_positions_l) == 'idd')\n",
2034 "assert(enigma.peg_positions == ([8], [22], [18]))\n",
2035 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xcbfvdnouptmlghjzwykierasq')\n",
2036 "\n",
2037 "enigma.advance()\n",
2038 "assert(enigma.wheel_positions == (3, 10, 7))\n",
2039 "assert(cat(enigma.wheel_positions_l) == 'ide')\n",
2040 "assert(enigma.peg_positions == ([8], [22], [17]))\n",
2041 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xfvglbdynuseriwqpmkzjcoaht')\n",
2042 "\n",
2043 "enigma.advance()\n",
2044 "assert(enigma.wheel_positions == (3, 10, 8))\n",
2045 "assert(cat(enigma.wheel_positions_l) == 'idf')\n",
2046 "assert(enigma.peg_positions == ([8], [22], [16]))\n",
2047 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'tfpqlbouynsewjgcdxkahzmriv')\n",
2048 "\n",
2049 "enigma.advance()\n",
2050 "assert(enigma.wheel_positions == (3, 10, 9))\n",
2051 "assert(cat(enigma.wheel_positions_l) == 'idg')\n",
2052 "assert(enigma.peg_positions == ([8], [22], [15]))\n",
2053 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cjaunvlwtbygzexrspqidfhokm')\n",
2054 "\n",
2055 "enigma.advance()\n",
2056 "assert(enigma.wheel_positions == (3, 10, 10))\n",
2057 "assert(cat(enigma.wheel_positions_l) == 'idh')\n",
2058 "assert(enigma.peg_positions == ([8], [22], [14]))\n",
2059 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'yltxkrqvowebzpingfucshjdam')\n",
2060 "\n",
2061 "enigma.advance()\n",
2062 "assert(enigma.wheel_positions == (3, 10, 11))\n",
2063 "assert(cat(enigma.wheel_positions_l) == 'idi')\n",
2064 "assert(enigma.peg_positions == ([8], [22], [13]))\n",
2065 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'myktluzrnxceaiqsohpdfwvjbg')\n",
2066 "\n",
2067 "enigma.advance()\n",
2068 "assert(enigma.wheel_positions == (3, 10, 12))\n",
2069 "assert(cat(enigma.wheel_positions_l) == 'idj')\n",
2070 "assert(enigma.peg_positions == ([8], [22], [12]))\n",
2071 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pynjrmiugdqxfcvakewzhoslbt')\n",
2072 "\n",
2073 "enigma.advance()\n",
2074 "assert(enigma.wheel_positions == (3, 10, 13))\n",
2075 "assert(cat(enigma.wheel_positions_l) == 'idk')\n",
2076 "assert(enigma.peg_positions == ([8], [22], [11]))\n",
2077 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mwvedyplnoxhaijgrqtszcbkfu')\n",
2078 "\n",
2079 "enigma.advance()\n",
2080 "assert(enigma.wheel_positions == (3, 10, 14))\n",
2081 "assert(cat(enigma.wheel_positions_l) == 'idl')\n",
2082 "assert(enigma.peg_positions == ([8], [22], [10]))\n",
2083 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qcbrfeutvoxpnmjladzhgiykws')\n",
2084 "\n",
2085 "enigma.advance()\n",
2086 "assert(enigma.wheel_positions == (3, 10, 15))\n",
2087 "assert(cat(enigma.wheel_positions_l) == 'idm')\n",
2088 "assert(enigma.peg_positions == ([8], [22], [9]))\n",
2089 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'dnoahryetsmukbcvwfjilpqzgx')\n",
2090 "\n",
2091 "enigma.advance()\n",
2092 "assert(enigma.wheel_positions == (3, 10, 16))\n",
2093 "assert(cat(enigma.wheel_positions_l) == 'idn')\n",
2094 "assert(enigma.peg_positions == ([8], [22], [8]))\n",
2095 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nidcfehgbqsovalyjzkxwmutpr')\n",
2096 "\n",
2097 "enigma.advance()\n",
2098 "assert(enigma.wheel_positions == (3, 10, 17))\n",
2099 "assert(cat(enigma.wheel_positions_l) == 'ido')\n",
2100 "assert(enigma.peg_positions == ([8], [22], [7]))\n",
2101 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'joifxdulcarhzpbntkwqgysevm')\n",
2102 "\n",
2103 "enigma.advance()\n",
2104 "assert(enigma.wheel_positions == (3, 10, 18))\n",
2105 "assert(cat(enigma.wheel_positions_l) == 'idp')\n",
2106 "assert(enigma.peg_positions == ([8], [22], [6]))\n",
2107 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ptnlsxvozmwdjchayuebrgkfqi')\n",
2108 "\n",
2109 "enigma.advance()\n",
2110 "assert(enigma.wheel_positions == (3, 10, 19))\n",
2111 "assert(cat(enigma.wheel_positions_l) == 'idq')\n",
2112 "assert(enigma.peg_positions == ([8], [22], [5]))\n",
2113 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'slwopzqnmxybihdeguavrtcjkf')\n",
2114 "\n",
2115 "enigma.advance()\n",
2116 "assert(enigma.wheel_positions == (3, 10, 20))\n",
2117 "assert(cat(enigma.wheel_positions_l) == 'idr')\n",
2118 "assert(enigma.peg_positions == ([8], [22], [4]))\n",
2119 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hcbedwlamzogixkytsrqvufnpj')\n",
2120 "\n",
2121 "enigma.advance()\n",
2122 "assert(enigma.wheel_positions == (3, 10, 21))\n",
2123 "assert(cat(enigma.wheel_positions_l) == 'ids')\n",
2124 "assert(enigma.peg_positions == ([8], [22], [3]))\n",
2125 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'odxbjwzrmelkisavuhnyqpfctg')\n",
2126 "\n",
2127 "enigma.advance()\n",
2128 "assert(enigma.wheel_positions == (3, 10, 22))\n",
2129 "assert(cat(enigma.wheel_positions_l) == 'idt')\n",
2130 "assert(enigma.peg_positions == ([8], [22], [2]))\n",
2131 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'udgbfeclrwnhxksvtioqapjmzy')\n",
2132 "\n",
2133 "enigma.advance()\n",
2134 "assert(enigma.wheel_positions == (3, 10, 23))\n",
2135 "assert(cat(enigma.wheel_positions_l) == 'idu')\n",
2136 "assert(enigma.peg_positions == ([8], [22], [1]))\n",
2137 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nrdczqxmowvshaiufblypkjgte')\n",
2138 "\n",
2139 "enigma.advance()\n",
2140 "assert(enigma.wheel_positions == (3, 10, 24))\n",
2141 "assert(cat(enigma.wheel_positions_l) == 'idv')\n",
2142 "assert(enigma.peg_positions == ([8], [22], [0]))\n",
2143 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hkifjdoacebqtzgulyvmpsxwrn')\n",
2144 "\n",
2145 "enigma.advance()\n",
2146 "assert(enigma.wheel_positions == (3, 11, 25))\n",
2147 "assert(cat(enigma.wheel_positions_l) == 'iew')\n",
2148 "assert(enigma.peg_positions == ([8], [21], [25]))\n",
2149 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'yptzuhofqvnmlkgbixwcejsrad')\n",
2150 "\n",
2151 "enigma.advance()\n",
2152 "assert(enigma.wheel_positions == (3, 11, 0))\n",
2153 "assert(cat(enigma.wheel_positions_l) == 'iex')\n",
2154 "assert(enigma.peg_positions == ([8], [21], [24]))\n",
2155 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'vkdcwhqfjibzsptngumoraeyxl')\n",
2156 "\n",
2157 "enigma.advance()\n",
2158 "assert(enigma.wheel_positions == (3, 11, 1))\n",
2159 "assert(cat(enigma.wheel_positions_l) == 'iey')\n",
2160 "assert(enigma.peg_positions == ([8], [21], [23]))\n",
2161 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'wenpbqrouxlkychdfgzvitajms')\n",
2162 "\n",
2163 "enigma.advance()\n",
2164 "assert(enigma.wheel_positions == (3, 11, 2))\n",
2165 "assert(cat(enigma.wheel_positions_l) == 'iez')\n",
2166 "assert(enigma.peg_positions == ([8], [21], [22]))\n",
2167 "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'szgyqvclkoihurjwenaxmfptdb')\n",
2168 "\n"
2169 ]
2170 }
2171 ],
2172 "source": [
2173 "enigma.set_wheels('i', 'd', 'z')\n",
2174 "\n",
2175 "for i in range(26):\n",
2176 " enigma.advance()\n",
2177 " print('enigma.advance()')\n",
2178 " print(\"assert(enigma.wheel_positions == {})\".format(enigma.wheel_positions))\n",
2179 " print(\"assert(cat(enigma.wheel_positions_l) == '{}')\".format(cat(enigma.wheel_positions_l)))\n",
2180 " print(\"assert(enigma.peg_positions == {})\".format(enigma.peg_positions))\n",
2181 " print(\"assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == '{}')\".format(cat(enigma.lookup(l) for l in string.ascii_lowercase)))\n",
2182 " print()"
2183 ]
2184 },
2185 {
2186 "cell_type": "code",
2187 "execution_count": 86,
2188 "metadata": {
2189 "collapsed": true
2190 },
2191 "outputs": [],
2192 "source": [
2193 "# Reflector B\n",
2194 "# Rotors III, I, II with rings 17, 11, 19\n",
2195 "# Plugboard pairs GU FZ BD LK TC PS HV WN JE AM\n",
2196 "\n",
2197 "tbt_enigma = Enigma(reflector_b_spec, \n",
2198 " wheel_iii_spec, wheel_iii_pegs,\n",
2199 " wheel_i_spec, wheel_i_pegs,\n",
2200 " wheel_ii_spec, wheel_ii_pegs,\n",
2201 " 17, 11, 19,\n",
2202 " 'GU FZ BD LK TC PS HV WN JE AM'.lower())"
2203 ]
2204 },
2205 {
2206 "cell_type": "code",
2207 "execution_count": 61,
2208 "metadata": {},
2209 "outputs": [
2210 {
2211 "data": {
2212 "text/plain": [
2213 "'jbvbwwzfslhxnhzzccsngebmrnswgjonwbjnzcfgadeuoyameylmpvny'"
2214 ]
2215 },
2216 "execution_count": 61,
2217 "metadata": {},
2218 "output_type": "execute_result"
2219 }
2220 ],
2221 "source": [
2222 "tbt_enigma.set_wheels('a', 'q', 'v')\n",
2223 "ct = tbt_enigma.encipher('verylongtestmessagewithanextrabitofmessageforgoodmeasure')\n",
2224 "ct"
2225 ]
2226 },
2227 {
2228 "cell_type": "code",
2229 "execution_count": 62,
2230 "metadata": {},
2231 "outputs": [
2232 {
2233 "data": {
2234 "text/plain": [
2235 "'slgncszxltkzebghstgywdmpr'"
2236 ]
2237 },
2238 "execution_count": 62,
2239 "metadata": {},
2240 "output_type": "execute_result"
2241 }
2242 ],
2243 "source": [
2244 "target_ct = ''.join(c.lower() for c in 'SLGNC SZXLT KZEBG HSTGY WDMPR' if c in string.ascii_letters)\n",
2245 "target_ct"
2246 ]
2247 },
2248 {
2249 "cell_type": "code",
2250 "execution_count": 63,
2251 "metadata": {},
2252 "outputs": [
2253 {
2254 "data": {
2255 "text/plain": [
2256 "'theyweredetectebybritishshipsinclud'"
2257 ]
2258 },
2259 "execution_count": 63,
2260 "metadata": {},
2261 "output_type": "execute_result"
2262 }
2263 ],
2264 "source": [
2265 "target_pt = ''.join(c.lower() for c in 'Theyw erede tecte byBri tishs hipsi nclud' if c in string.ascii_letters)\n",
2266 "target_pt"
2267 ]
2268 },
2269 {
2270 "cell_type": "code",
2271 "execution_count": 91,
2272 "metadata": {},
2273 "outputs": [
2274 {
2275 "data": {
2276 "text/plain": [
2277 "'theyweredetectedbybritishshipsinclud'"
2278 ]
2279 },
2280 "execution_count": 91,
2281 "metadata": {},
2282 "output_type": "execute_result"
2283 }
2284 ],
2285 "source": [
2286 "target_pt = ''.join(c.lower() for c in 'Theyw erede tecte d byBri tishs hipsi nclud' if c in string.ascii_letters)\n",
2287 "target_pt"
2288 ]
2289 },
2290 {
2291 "cell_type": "code",
2292 "execution_count": 64,
2293 "metadata": {},
2294 "outputs": [
2295 {
2296 "data": {
2297 "text/plain": [
2298 "(25, 35)"
2299 ]
2300 },
2301 "execution_count": 64,
2302 "metadata": {},
2303 "output_type": "execute_result"
2304 }
2305 ],
2306 "source": [
2307 "len(target_ct), len(target_pt)"
2308 ]
2309 },
2310 {
2311 "cell_type": "code",
2312 "execution_count": 88,
2313 "metadata": {},
2314 "outputs": [
2315 {
2316 "name": "stdout",
2317 "output_type": "stream",
2318 "text": [
2319 "slgncszxltkzebghstgywdmpr\n",
2320 "theyweredetectebybritishshipsinclud\n"
2321 ]
2322 }
2323 ],
2324 "source": [
2325 "print('{}\\n{}'.format(target_ct, target_pt))"
2326 ]
2327 },
2328 {
2329 "cell_type": "code",
2330 "execution_count": 92,
2331 "metadata": {},
2332 "outputs": [
2333 {
2334 "name": "stdout",
2335 "output_type": "stream",
2336 "text": [
2337 "theyweredetectedbybritishshipsinclud\n",
2338 "slgncszxltkzebghstgywdmpr\n",
2339 "slgncszxltkzebghstgywdmprucuzqdqzpve\n",
2340 "theyweredetectedbybritish\n"
2341 ]
2342 }
2343 ],
2344 "source": [
2345 "tbt_enigma.set_wheels('a', 'a', 'a')\n",
2346 "this_pt = tbt_enigma.encipher(target_ct)\n",
2347 "\n",
2348 "tbt_enigma.set_wheels('a', 'a', 'a')\n",
2349 "this_ct = tbt_enigma.encipher(target_pt)\n",
2350 "\n",
2351 "\n",
2352 "print('{}\\n{}\\n{}\\n{}'.format(target_pt, target_ct, this_ct, this_pt))"
2353 ]
2354 },
2355 {
2356 "cell_type": "code",
2357 "execution_count": 65,
2358 "metadata": {
2359 "collapsed": true
2360 },
2361 "outputs": [],
2362 "source": [
2363 "import itertools"
2364 ]
2365 },
2366 {
2367 "cell_type": "code",
2368 "execution_count": 67,
2369 "metadata": {
2370 "collapsed": true
2371 },
2372 "outputs": [],
2373 "source": [
2374 "def str_ham(s1, s2):\n",
2375 " \"\"\"Hamming distance for strings\"\"\"\n",
2376 " return sum(1 for c1, c2 in zip(s1, s2) if c1 == c2)"
2377 ]
2378 },
2379 {
2380 "cell_type": "code",
2381 "execution_count": 68,
2382 "metadata": {},
2383 "outputs": [
2384 {
2385 "data": {
2386 "text/plain": [
2387 "5"
2388 ]
2389 },
2390 "execution_count": 68,
2391 "metadata": {},
2392 "output_type": "execute_result"
2393 }
2394 ],
2395 "source": [
2396 "str_ham('hello', 'hello')"
2397 ]
2398 },
2399 {
2400 "cell_type": "code",
2401 "execution_count": 93,
2402 "metadata": {},
2403 "outputs": [
2404 {
2405 "name": "stdout",
2406 "output_type": "stream",
2407 "text": [
2408 "best ('a', 'a', 'a') 25\n",
2409 "best ('a', 'a', 'a') 25\n",
2410 "best ('a', 'a', 'a') 25\n",
2411 "best ('a', 'a', 'a') 25\n",
2412 "1 loop, best of 3: 17.6 s per loop\n"
2413 ]
2414 }
2415 ],
2416 "source": [
2417 "%%timeit\n",
2418 "best = ('a', 'a', 'a')\n",
2419 "best_hd = 0\n",
2420 "for w1, w2, w3 in itertools.product(string.ascii_lowercase, repeat=3):\n",
2421 " tbt_enigma.set_wheels(w1, w2, w3)\n",
2422 " this_ct = tbt_enigma.encipher(target_pt)\n",
2423 " if this_ct == target_ct:\n",
2424 " print(w1, w2, w3)\n",
2425 " if str_ham(this_ct, target_ct) > best_hd:\n",
2426 " best = (w1, w2, w3)\n",
2427 " best_hd = str_ham(this_ct, target_ct)\n",
2428 "print('best', best, best_hd)"
2429 ]
2430 },
2431 {
2432 "cell_type": "code",
2433 "execution_count": 94,
2434 "metadata": {},
2435 "outputs": [
2436 {
2437 "name": "stdout",
2438 "output_type": "stream",
2439 "text": [
2440 "Wheels now ['a', 'a', 'b'] enciphering t -> s\n",
2441 "Wheels now ['a', 'a', 'c'] enciphering h -> l\n",
2442 "Wheels now ['a', 'a', 'd'] enciphering e -> g\n",
2443 "Wheels now ['a', 'a', 'e'] enciphering y -> n\n",
2444 "Wheels now ['a', 'b', 'f'] enciphering w -> c\n",
2445 "Wheels now ['a', 'b', 'g'] enciphering e -> s\n",
2446 "Wheels now ['a', 'b', 'h'] enciphering r -> z\n",
2447 "Wheels now ['a', 'b', 'i'] enciphering e -> x\n",
2448 "Wheels now ['a', 'b', 'j'] enciphering d -> l\n",
2449 "Wheels now ['a', 'b', 'k'] enciphering e -> t\n",
2450 "Wheels now ['a', 'b', 'l'] enciphering t -> k\n",
2451 "Wheels now ['a', 'b', 'm'] enciphering e -> z\n",
2452 "Wheels now ['a', 'b', 'n'] enciphering c -> e\n",
2453 "Wheels now ['a', 'b', 'o'] enciphering t -> b\n",
2454 "Wheels now ['a', 'b', 'p'] enciphering e -> g\n",
2455 "Wheels now ['a', 'b', 'q'] enciphering d -> h\n",
2456 "Wheels now ['a', 'b', 'r'] enciphering b -> s\n",
2457 "Wheels now ['a', 'b', 's'] enciphering y -> t\n",
2458 "Wheels now ['a', 'b', 't'] enciphering b -> g\n",
2459 "Wheels now ['a', 'b', 'u'] enciphering r -> y\n",
2460 "Wheels now ['a', 'b', 'v'] enciphering i -> w\n",
2461 "Wheels now ['a', 'b', 'w'] enciphering t -> d\n",
2462 "Wheels now ['a', 'b', 'x'] enciphering i -> m\n",
2463 "Wheels now ['a', 'b', 'y'] enciphering s -> p\n",
2464 "Wheels now ['a', 'b', 'z'] enciphering h -> r\n",
2465 "Wheels now ['a', 'b', 'a'] enciphering s -> u\n",
2466 "Wheels now ['a', 'b', 'b'] enciphering h -> c\n",
2467 "Wheels now ['a', 'b', 'c'] enciphering i -> u\n",
2468 "Wheels now ['a', 'b', 'd'] enciphering p -> z\n",
2469 "Wheels now ['a', 'b', 'e'] enciphering s -> q\n",
2470 "Wheels now ['a', 'c', 'f'] enciphering i -> d\n",
2471 "Wheels now ['a', 'c', 'g'] enciphering n -> q\n",
2472 "Wheels now ['a', 'c', 'h'] enciphering c -> z\n",
2473 "Wheels now ['a', 'c', 'i'] enciphering l -> p\n",
2474 "Wheels now ['a', 'c', 'j'] enciphering u -> v\n",
2475 "Wheels now ['a', 'c', 'k'] enciphering d -> e\n"
2476 ]
2477 },
2478 {
2479 "data": {
2480 "text/plain": [
2481 "('slgncszxltkzebghstgywdmprucuzqdqzpve', 'slgncszxltkzebghstgywdmpr')"
2482 ]
2483 },
2484 "execution_count": 94,
2485 "metadata": {},
2486 "output_type": "execute_result"
2487 }
2488 ],
2489 "source": [
2490 "tbt_enigma.set_wheels('a', 'a', 'a')\n",
2491 "tbt_enigma.encipher(target_pt, debug=True), target_ct"
2492 ]
2493 },
2494 {
2495 "cell_type": "code",
2496 "execution_count": 95,
2497 "metadata": {},
2498 "outputs": [
2499 {
2500 "name": "stdout",
2501 "output_type": "stream",
2502 "text": [
2503 "Wheels now ['a', 'a', 'b'] enciphering s -> t\n",
2504 "Wheels now ['a', 'a', 'c'] enciphering l -> h\n",
2505 "Wheels now ['a', 'a', 'd'] enciphering g -> e\n",
2506 "Wheels now ['a', 'a', 'e'] enciphering n -> y\n",
2507 "Wheels now ['a', 'b', 'f'] enciphering c -> w\n",
2508 "Wheels now ['a', 'b', 'g'] enciphering s -> e\n",
2509 "Wheels now ['a', 'b', 'h'] enciphering z -> r\n",
2510 "Wheels now ['a', 'b', 'i'] enciphering x -> e\n",
2511 "Wheels now ['a', 'b', 'j'] enciphering l -> d\n",
2512 "Wheels now ['a', 'b', 'k'] enciphering t -> e\n",
2513 "Wheels now ['a', 'b', 'l'] enciphering k -> t\n",
2514 "Wheels now ['a', 'b', 'm'] enciphering z -> e\n",
2515 "Wheels now ['a', 'b', 'n'] enciphering e -> c\n",
2516 "Wheels now ['a', 'b', 'o'] enciphering b -> t\n",
2517 "Wheels now ['a', 'b', 'p'] enciphering g -> e\n",
2518 "Wheels now ['a', 'b', 'q'] enciphering h -> d\n",
2519 "Wheels now ['a', 'b', 'r'] enciphering s -> b\n",
2520 "Wheels now ['a', 'b', 's'] enciphering t -> y\n",
2521 "Wheels now ['a', 'b', 't'] enciphering g -> b\n",
2522 "Wheels now ['a', 'b', 'u'] enciphering y -> r\n",
2523 "Wheels now ['a', 'b', 'v'] enciphering w -> i\n",
2524 "Wheels now ['a', 'b', 'w'] enciphering d -> t\n",
2525 "Wheels now ['a', 'b', 'x'] enciphering m -> i\n",
2526 "Wheels now ['a', 'b', 'y'] enciphering p -> s\n",
2527 "Wheels now ['a', 'b', 'z'] enciphering r -> h\n"
2528 ]
2529 },
2530 {
2531 "data": {
2532 "text/plain": [
2533 "('theyweredetectedbybritish', 'theyweredetectedbybritishshipsinclud')"
2534 ]
2535 },
2536 "execution_count": 95,
2537 "metadata": {},
2538 "output_type": "execute_result"
2539 }
2540 ],
2541 "source": [
2542 "tbt_enigma.set_wheels('a', 'a', 'a')\n",
2543 "tbt_enigma.encipher(target_ct, debug=True), target_pt"
2544 ]
2545 },
2546 {
2547 "cell_type": "code",
2548 "execution_count": 96,
2549 "metadata": {},
2550 "outputs": [
2551 {
2552 "data": {
2553 "text/plain": [
2554 "('theyweredetectedbybritish', 'theyweredetectedbybritishshipsinclud')"
2555 ]
2556 },
2557 "execution_count": 96,
2558 "metadata": {},
2559 "output_type": "execute_result"
2560 }
2561 ],
2562 "source": [
2563 "tbt_enigma.set_wheels('a', 'a', 'a')\n",
2564 "tbt_enigma.encipher(target_ct), target_pt"
2565 ]
2566 },
2567 {
2568 "cell_type": "code",
2569 "execution_count": 97,
2570 "metadata": {},
2571 "outputs": [
2572 {
2573 "data": {
2574 "text/plain": [
2575 "'mdtbjzuvielkawosqrpcghnxyf'"
2576 ]
2577 },
2578 "execution_count": 97,
2579 "metadata": {},
2580 "output_type": "execute_result"
2581 }
2582 ],
2583 "source": [
2584 "cat(tbt_enigma.plugboard.forward(l) for l in string.ascii_lowercase)"
2585 ]
2586 },
2587 {
2588 "cell_type": "code",
2589 "execution_count": 99,
2590 "metadata": {},
2591 "outputs": [
2592 {
2593 "data": {
2594 "text/plain": [
2595 "10"
2596 ]
2597 },
2598 "execution_count": 99,
2599 "metadata": {},
2600 "output_type": "execute_result"
2601 }
2602 ],
2603 "source": [
2604 "tbt_enigma.set_wheels('a', 'a', 'a')\n",
2605 "tbt_enigma.left_wheel.position"
2606 ]
2607 },
2608 {
2609 "cell_type": "code",
2610 "execution_count": null,
2611 "metadata": {
2612 "collapsed": true
2613 },
2614 "outputs": [],
2615 "source": []
2616 }
2617 ],
2618 "metadata": {
2619 "kernelspec": {
2620 "display_name": "Python 3",
2621 "language": "python",
2622 "name": "python3"
2623 },
2624 "language_info": {
2625 "codemirror_mode": {
2626 "name": "ipython",
2627 "version": 3
2628 },
2629 "file_extension": ".py",
2630 "mimetype": "text/x-python",
2631 "name": "python",
2632 "nbconvert_exporter": "python",
2633 "pygments_lexer": "ipython3",
2634 "version": "3.5.3"
2635 }
2636 },
2637 "nbformat": 4,
2638 "nbformat_minor": 1
2639 }