I have the incrementor working properly, (at least in the forward direction, bucause I'm not sure how to use the notches
on the reverse trip.
What I'm still not sure of is the way the rotor's rotation affects the cipher output,
because following Tony Sands example, it doesn't seem to have an effect. In addition,
I'm sure I've got the rotation increment correct in the forward direction, but still not clear on the reverse direction action.
New code Incrementor.py with full test (built into script) is now on github:
Testing against the Tony Sands example, here are the results:
First the code:
on the reverse trip.
What I'm still not sure of is the way the rotor's rotation affects the cipher output,
because following Tony Sands example, it doesn't seem to have an effect. In addition,
I'm sure I've got the rotation increment correct in the forward direction, but still not clear on the reverse direction action.
New code Incrementor.py with full test (built into script) is now on github:
Testing against the Tony Sands example, here are the results:
First the code:
import json import EnigmaPaths class Incrementor: def __init__(self, rinfo, start_index=0): """ Initialize - load rotor info, set starting indexes, get cipher :param rinfo: """ self.epath = EnigmaPaths.EnigmaPaths() with self.epath.enigma_info.open() as f: self.init_data = json.load(f) self.cipher = rinfo['cipher'] self.notch = rinfo['notches'][0] self.alpha = self.init_data['unencoded'] self.index = start_index self.max_index = len(self.cipher) - 1 def next_index(self): self.index += 1 if self.index > self.max_index: self.index = 0 return self.index def get_next_item(self, alpha_char, direction='f', preincrement=False): index = self.index if preincrement: index = self.next_index() if direction == 'f': aidx = self.alpha.index(alpha_char) item = self.cipher[aidx] else: cidx = self.cipher.index(alpha_char) item = self.alpha[cidx] advance = (self.alpha[index] == self.notch) if not preincrement: index = self.next_index() return item, advance def set_initial_index(self, index): if index >= len(self.cipher): print(f'index out of range, valid range is 0 - {self.max_index}') else: self.index = index def query_cipher(self): return self.cipher def query_index(self): return self.index def query_notch(self): return self.notch def testit(): # Order if progression is from right to left (rotors) # Assume 'B' selected for reflector # Our test letter. test_letter = 'G' # Setup right rotor(start index = 2, set by set_initial_index): rinfo = {'name': 'rotor3', 'cipher': 'BDFHJLCPRTXVZNYEIWGAKMUSQO', 'notches': ['W']} r_incrementor = Incrementor(rinfo) # Get reflector here (needed init_data to be visible test_reflector = r_incrementor.init_data['reflector_B'] r_incrementor.set_initial_index(2) print(f'\nright alpha: {r_incrementor.alpha}') print(f'right cipher: {r_incrementor.query_cipher()}') print(f'right index: {r_incrementor.query_index()}') print(f'right notch: {r_incrementor.query_notch()}') # Setup middle rotor (start index = 4 'S'): rinfo = {'name': 'rotor2', 'cipher': 'AJDKSIRUXBLHWTMCQGZNPYFVOE', 'notches': ['F']} m_incrementor = Incrementor(rinfo, start_index=4) print(f'\nmiddle alpha: {m_incrementor.alpha}') print(f'middle cipher: {m_incrementor.query_cipher()}') print(f'middle index: {m_incrementor.query_index()}') print(f'middle notch: {m_incrementor.query_notch()}') # Setup left rotor (start index = 16): rinfo = {'name': 'rotor1', 'cipher': 'EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'notches': ['R']} l_incrementor = Incrementor(rinfo, start_index=16) print(f'\nleft alpha: {l_incrementor.alpha}') print(f'left cipher: {l_incrementor.query_cipher()}') print(f'left index: {l_incrementor.query_index()}') print(f'left notch: {l_incrementor.query_notch()}') # Test one letter through entire process # First get right rotor cipher and advance rotor ritem, advance = r_incrementor.get_next_item(test_letter, direction='f') print(f'\nright rotor cipher: in: {test_letter}, out: {ritem}, advance: {advance}') # if advance is True increment middle rotor by 1 # ignore cipher, in each case but check advance again if advance: # This means slot was encountered on middle advance, so # have to advance left! mitem, advance = m_incrementor.get_next_item(ritem, direction='f') if advance: # This means middle slot was encountered on advance litem, advance = l_incrementor.get_next_item(mitem, direction='f') # Get middle rotor cipher and advance rotor mitem, advance = m_incrementor.get_next_item(ritem, direction='f') print(f'\nmiddle rotor cipher: in: {ritem}, out: {mitem}, advance: {advance}') if advance: # This means middle slot was encountered on advance litem, advance = l_incrementor.get_next_item(mitem, direction='f') litem, advance = l_incrementor.get_next_item(mitem, direction='f') print(f'\nleft rotor cipher: in: {mitem} out: {litem}, advance: {advance}') # Read up on what to do if advance = true, is the middle # advanced?? # run through reflector aidx = l_incrementor.alpha.index(litem) refl_item = test_reflector[aidx] print(f'\nreflector output: in: {litem}, out: {refl_item}') # reverse trip print('Return trip') litem, advance = l_incrementor.get_next_item(refl_item, direction='r') print(f'\nleft rotor cipher: in: {refl_item}, out: {litem}, advance: {advance}') # Read up on what to do if advance = true, is the middle # advanced?? # Get middle rotor cipher and advance rotor mitem, advance = m_incrementor.get_next_item(litem, direction='r') print(f'\nmiddle rotor cipher: in: {litem}, out: {mitem}, advance: {advance}') ritem, advance = r_incrementor.get_next_item(mitem, direction='r') print(f'\nright rotor cipher: in: {mitem}, out: {ritem}, advance: {advance}') print(f'\n\nletter in: {test_letter}, letter out: {ritem}') if __name__ == '__main__': testit()and built in test results:
Output:right alpha: ABCDEFGHIJKLMNOPQRSTUVWXYZ
right cipher: BDFHJLCPRTXVZNYEIWGAKMUSQO
right index: 2
right notch: W
middle alpha: ABCDEFGHIJKLMNOPQRSTUVWXYZ
middle cipher: AJDKSIRUXBLHWTMCQGZNPYFVOE
middle index: 4
middle notch: F
left alpha: ABCDEFGHIJKLMNOPQRSTUVWXYZ
left cipher: EKMFLGDQVZNTOWYHXUSPAIBRCJ
left index: 16
left notch: R
right rotor cipher: in: G, out: C, advance: False
middle rotor cipher: in: C, out: D, advance: False
left rotor cipher: in: D out: F, advance: False
reflector output: in: F, out: S
Return trip
left rotor cipher: in: S, out: S, advance: True
middle rotor cipher: in: S, out: E, advance: True
right rotor cipher: in: E, out: P, advance: False
letter in: G, letter out: P