changeset 19:800a8467f07a

Testing with complete part 1 of 14 part message. One letter is wrong out of 1285. Debugging was added to try and track it down. No solution yet.
author Brian Neal <bgneal@gmail.com>
date Tue, 10 Dec 2013 21:49:36 -0600
parents 168a6017eb89
children 37eab2f88dcc
files purple/machine.py purple/tests/test_machine.py
diffstat 2 files changed, 109 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/purple/machine.py	Wed Dec 04 20:31:37 2013 -0600
+++ b/purple/machine.py	Tue Dec 10 21:49:36 2013 -0600
@@ -128,8 +128,6 @@
         self.alphabet = alphabet
         self.plugboard = {c : n for n, c in enumerate(alphabet)}
 
-        self.middle_switch_catchup = False
-
     @classmethod
     def from_key_sheet(cls, switches, alphabet=None):
         """This class method allows one to construct a Purple97 using
@@ -184,11 +182,16 @@
 
         """
         plaintext = []
-        for c in ciphertext:
+        for i, c in enumerate(ciphertext):
             if c not in self.VALID_KEYS:
                 raise Purple97Error("invalid input '{}' to decrypt".format(c))
 
             n = self.plugboard[c]
+
+            if i == 490 or i == 491:
+                print(self.sixes.pos, self.fast_switch.pos,
+                        self.middle_switch.pos, self.slow_switch.pos)
+
             if n < 6:
                 # This input goes to the sixes switch
                 x = self.sixes.decrypt(n)
@@ -204,6 +207,10 @@
             # Now step the switches.
             self.step()
 
+            if i == 490 or i == 491:
+                print(self.sixes.pos, self.fast_switch.pos,
+                        self.middle_switch.pos, self.slow_switch.pos)
+
         return ''.join(plaintext)
 
     def encrypt(self, plaintext):
@@ -257,34 +264,13 @@
         # However if the sixes is at the last position (24), the middle
         # switch steps instead.
         #
-        # But if the sixes is at the last position (24) and the middle
-        # switch is at the last position (24), the slow switch will step.
-        # The middle switch will step on the next letter in this case.
-        #
-        # Here we reproduce figure 10 from the reference paper with offsets
-        # adjusted for 0-based indexing to illustrate the movement. In this
-        # example the fast is twenties #1, middle is #2, and slow is #3.
-        #
-        # Sixes     Twenties #1     Twenties #2     Twenties #3
-        # -----------------------------------------------------
-        #   20          0               24              4
-        #   21          1               24              4
-        #   22          2               24              4
-        #   23          3               24              4
-        # * 24          3               24              5
-        # #  0          3                0              5
-        #    1          4                0              5
-        #
-        # Here we see the fast switch stepping. However at (*) both the
-        # sixes and middle switch have reached their last positions, so the
-        # slow switch steps. At the next letter (#) the middle switch plays
-        # "catch up" and advances while the fast switch holds steady.
+        # But if the sixes is at the second to last position (23) and the middle
+        # switch is at the last position (24), the slow switch will step.  The
+        # middle switch will step on the next letter in this case.
 
-        if sixes_pos == 24 and middle_pos == 24:
+        if sixes_pos == 23 and middle_pos == 24:
             self.slow_switch.step()
-            self.middle_switch_catchup = True
-        elif sixes_pos == 24 or self.middle_switch_catchup:
+        elif sixes_pos == 24:
             self.middle_switch.step()
-            self.middle_switch_catchup = False
         else:
             self.fast_switch.step()
--- a/purple/tests/test_machine.py	Wed Dec 04 20:31:37 2013 -0600
+++ b/purple/tests/test_machine.py	Tue Dec 10 21:49:36 2013 -0600
@@ -9,24 +9,90 @@
 from purple.switch import SteppingSwitchError
 
 
-# The ciphertext contains garbles, indicated by '-' chars.
-ciphertext = (
-    "ZTXODNWKCCMAVNZXYWEETUQTCIMN"
-    "VEUVIWBLUAXRRTLVARGNTPCNOIUP"
-    "JLCIVRTPJKAUHVMUDTHKTXYZELQTVWGBUHFAWSHU"
-    "LBFBHEXMYHFLOWD-KWHKKNXEBVPYHHGHEKXIOHQ"
-    "HUHWIKYJYHPPFEALNNAKIBOOZNFRLQCFLJTTSSDDOIOCVT-"
-    "ZCKQTSHXTIJCNWXOKUFNQR-TAOIHWTATWV"
-)
+# This is part 1 of the famous 14 part message. The ciphertext and plaintext are
+# laid on top of each other, every other line, with blank lines inserted for
+# clarity. Garbles are indicated by '-' characters.
+#
+part1 = """
+ZTXODNWKCCMAVNZXYWEETUQTCIMNVEUVIWBLUAXRRTLVA
+FOVTATAKIDASINIMUIMINOMOXIWOIRUBESIFYXXFCKZZR
 
-plaintext = (
-    "FOVTATAKIDASINIMUIMINOMOXIWO"
-    "IRUBESIFYXXFCKZZRDXOOVBTNFYX"
-    "FAEMEMORANDUMFIOFOVOOMOJIBAKARIFYXRAICCY"
-    "LFCBBCFCTHEGOVE-NMENTOFJAPANLFLPROMPTED"
-    "BYAGENUINEDESIRETOCOMETOANAMICABLEUNDERSTANDIN-"
-    "WITHTHEGOVERNMENTOFTHE-NITEDSTATES"
-)
+RGNTPCNOIUPJLCIVRTPJKAUHVMUDTHKTXYZELQTVWGBUHFAWSH
+DXOOVBTNFYXFAEMEMORANDUMFIOFOVOOMOJIBAKARIFYXRAICC
+
+ULBFBHEXMYHFLOWD-KWHKKNXEBVPYHHGHEKXIOHQHUHWIKYJYH
+YLFCBBCFCTHEGOVE-NMENTOFJAPANLFLPROMPTEDBYAGENUINE
+
+PPFEALNNAKIBOOZNFRLQCFLJTTSSDDOIOCVT-ZCKQTSHXTIJCN
+DESIRETOCOMETOANAMICABLEUNDERSTANDIN-WITHTHEGOVERN
+
+WXOKUFNQR-TAOIHWTATWVHOTGCGAKVANKZANMUIN
+MENTOFTHE-NITEDSTATESINORDERTHATTHETWOCO
+
+YOYJFSRDKKSEQBWKIOORJAUWKXQGUWPDUDZNDRMDHVHYPNIZXB
+UNTRIESBYTHEIRJOINTEFFORTSMAYSECURETHEPEACEOFTHEPA
+
+GICXRMAWMFTIUDBXIENLONOQVQKYCOTVSHVNZZQPDLMXVNRUUN
+CIFICAREAANDTHEREBYCONTRIBUTETOWARDTHEREALIZATIONO
+
+QFTCDFECZDFGMXEHHWYONHYNJDOVJUNCSUVKKEIWOLKRBUUSOZ
+FWORLDPEACELFLHASCONTINUEDNEGOTIATIONSWITHTHEUTMOS
+
+UIGNISMWUOSBOBLJXERZJEQYQMTFTXBJNCMJKVRKOTSOPBOYMK
+TSINCERITYSINCEAPRILLASTWITHTHEGOVERNMENTOFTHEUNIT
+
+IRETINCPSQJAWVHUFKRMAMXNZUIFNOPUEMHGLOEJHZOOKHHEED
+EDSTATESREGARDINGTHEADJUSTMENTANDADVANCEMENTOFJAPA
+
+NIHXFXFXGPDZBSKAZABYEKYEPNIYSHVKFRFPVCJTPTOYCNEIQB
+NESEVVDAMERICANRELATIONSANDTHESTABILIZATIONOFTHEPA
+
+FEXMERMIZLGDRXZORLZFSQYPZFATZCHUGRNHWDDTAIHYOOCOOD
+CIFICAREACFCCCFTHEJAPANESEQOVERNMENXHASTHEHONORTOS
+
+UZYIWJROOJUMUIHRBEJFONAXGNCKAOARDIHCDZKIXPR--DIMUW
+TATEFRANKLYITSVIEWSCONCERNINGTHECLAIMSTHEAM--VCANG
+
+OMHLTJSOUXPFKGEPWJOMTUVKMWRKTACUPIGAFEDFVRKXFXLFGU
+OVERNMENTHASUERSISTENTLYMAINTAINEDASWELLASTHEMEASU
+
+RDETJIYOLKBHZKXOJDDOVRHMMUQBFOWRODMRMUWNAYKYPISDLH
+RESTHEUNITEDSTATESANDGREATBRITAINHAVETAKENTOWARDJA
+
+ECKINLJORKWNWXADAJOLONOEVMUQDFIDSPEBBPWROFBOPAZJEU
+PANDURINGTHKSEEIGHTMONTHSCYCCCFLFCDDCFCITISTHEIMMU
+
+USBHGIORCSUUQKIIEHPCTJRWSOGLETZLOUKKEOJOSMKJBWUCDD
+TABLXPOLWCYOFTHEJAPANESEGOVERNMENTTOINSURETHESTABI
+
+CPYUUWCSSKWWVLIUPKYXGKQOKAZTEZFHGVPJFEWEUBKLIZLWKK
+LITYOFEASTASIAANDTOPROMOTEWORLZPEACELFLANDTHEREBYT
+
+OBXLEPQPDATWUSUUPKYRHNWDZXXGTWDDNSHDCBCJXAOOEEPUBP
+OEIABLEALLNATIONSTOFINDEACHITSPROPERPLACEINTHEWORL
+
+WFRBQSFXSEZJJYAANMG-WLYMGWAQDGIVNOHKOUTIXYFOKNGGBF
+DCFCCCFEVERSINCETHE-HINAAFFAIRBROKEOUTOWINGTOTHEFA
+
+GANPWTUYLBEFFKUFLEXOIUUANVMMJEQUSFHFDOHQLAKWTBYYYL
+ILUREONTHEPARTOFCHINATOCOMPREHENLJAPANVCFSTRUEYNTE
+
+NTLYTSXCGKCEEWQRYAVGRKXIANPXNOFVXGKJFAVKLTHOCXCIVK
+NTIONSLFLTWEJAPANESEGOVERNMENTHASSTRIVENFORTHEREST
+
+OLXTJTUNCLQCICRUIIWQDDMOTPRVTJKKSKFHXFKMDIKIZWROGZ
+ORATIONOFPEACEANDIMHASCONSISTENTLYEXERTEDITSBESTEF
+
+JYMTMNOVMFJ-OKTEIVMYANOHNNYPDLEXCFRRNEBLMNYEBGNHCZ
+FORTSTOPREV-NTTHEEXTENTIONOFWARVVFLIKEVISTURBANCES
+
+ZCFNWGGRHRIUUTTILKLODUYZKQOZMMNHASXHLPVTNGHQDAJIUG
+CFCNSIASALSOTOTHATENDTNATINSEPTEMBERLASTYEARJAPANC
+
+OOSZ-----ZRTGWFBLKI--------YBDABJ-----WYOEANV---OM
+ONCL-----HETRIPAITI--------THGERM-----DYTALYC---OV
+"""
+
 
 class Purple97TestCase(unittest.TestCase):
 
@@ -111,7 +177,11 @@
         self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,2,20-1a')
         self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,2,20-123')
 
-    def test_decrypt_first_part_of_14_part_message(self):
+    def test_decrypt_part_1_message(self):
+
+        lines = part1.split()
+        ciphertext = ''.join(lines[0::2])
+        plaintext = ''.join(lines[1::2])
 
         # Use 'X' in place of the garbles
         input_text = ciphertext.replace('-', 'X')
@@ -128,6 +198,7 @@
         mismatches = []
         for n, (a, b) in enumerate(zip(plaintext, actual)):
             if a != b and a != '-':
+                import pdb; pdb.set_trace()
                 mismatches.append(n)
 
         msg = None
@@ -137,7 +208,11 @@
 
         self.assertTrue(len(mismatches) == 0, msg)
 
-    def test_encrypt_first_part_of_14_part_message(self):
+    def test_encrypt_part_1_message(self):
+
+        lines = part1.split()
+        ciphertext = ''.join(lines[0::2])
+        plaintext = ''.join(lines[1::2])
 
         # Use 'X' in place of the garbles
         input_text = plaintext.replace('-', 'X')