Mercurial > public > purple
changeset 16:adaca0a6b2b4
Build encrypt wiring tables once.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Tue, 03 Dec 2013 19:20:48 -0600 |
parents | 672ba8b2269f |
children | 0e5c0f2896be |
files | purple/data.py purple/switch.py purple/tests/test_switch.py |
diffstat | 3 files changed, 86 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- a/purple/data.py Mon Dec 02 20:58:36 2013 -0600 +++ b/purple/data.py Tue Dec 03 19:20:48 2013 -0600 @@ -132,9 +132,24 @@ # Convert wiring data to be 0-based. -_WIRING_DATA = [SIXES_DATA, TWENTIES_1_DATA, TWENTIES_2_DATA, TWENTIES_3_DATA] +DECRYPT_DATA = [SIXES_DATA, TWENTIES_1_DATA, TWENTIES_2_DATA, TWENTIES_3_DATA] -for table in _WIRING_DATA: +for table in DECRYPT_DATA: for i in range(len(table)): for j in range(len(table[i])): table[i][j] = table[i][j] - 1 + + +def build_encrypt_wiring(dec_wiring): + """This function builds a reciprocal encrypt wiring table from the supplied + decrypt wiring table. + + """ + enc_wiring = [] + for level in dec_wiring: + enc_wiring.append( + [level.index(n) for n in range(len(level))]) + return enc_wiring + +# Build reciprocal encrypt wiring tables: +ENCRYPT_DATA = [build_encrypt_wiring(wiring) for wiring in DECRYPT_DATA]
--- a/purple/switch.py Mon Dec 02 20:58:36 2013 -0600 +++ b/purple/switch.py Tue Dec 03 19:20:48 2013 -0600 @@ -21,25 +21,35 @@ in the PURPLE cipher machine. """ - def __init__(self, wiring, init_pos=0): - """Construct a SteppingSwitch from a wiring list, which must be a list + def __init__(self, dec_wiring, enc_wiring=None, init_pos=0): + """Construct a SteppingSwitch. + + dec_wiring is the decrypt wiring table, which must be a list of lists (one list per input level). Each inner list is a list of - integers representing the output contacts. The initial position of the - switch can also be set; this defaults to 0. + integers representing the output contacts. - The wiring lists are assumed to be 0-based and represent the decrypt - path through the switch. A reciprocal encrypt wiring map will be - constructed from this argument internally. + enc_wiring is the encrypt wiring table. If None, a reciprocal table is + built from the dec_wiring parameter. + + init_pos is the initial position of the switch; this defaults to 0. """ - self.dec_wiring = wiring - self.num_positions = len(wiring) - self.num_levels = len(wiring[0]) + self.dec_wiring = dec_wiring + self.num_positions = len(dec_wiring) + self.num_levels = len(dec_wiring[0]) - if not all(self.num_levels == len(level) for level in wiring): - raise SteppingSwitchError("Ragged wiring table") + if not all(self.num_levels == len(level) for level in self.dec_wiring): + raise SteppingSwitchError("Invalid decrypt wiring dimensions") - self._build_encrypt_wiring() + self.enc_wiring = (enc_wiring if enc_wiring else + data.build_encrypt_wiring(dec_wiring)) + + if self.num_positions != len(self.enc_wiring): + raise SteppingSwitchError("Encrypt/Decrypt positions mismatch") + + if not all(self.num_levels == len(level) for level in self.enc_wiring): + raise SteppingSwitchError("Invalid encrypt wiring dimensions") + self.set_pos(init_pos) def set_pos(self, pos): @@ -78,16 +88,6 @@ """ return self.enc_wiring[self.pos][level] - def _build_encrypt_wiring(self): - """This method builds an encrypt wiring table from the decrypt wiring - table member. - - """ - self.enc_wiring = [] - for level in self.dec_wiring: - self.enc_wiring.append( - [level.index(n) for n in range(self.num_levels)]) - def create_switch(switch_type, init_pos=0): """Factory function for building a SteppingSwitch of the requested @@ -102,14 +102,9 @@ A ValueError will be raised if switch_type is an illegal value. """ - wiring_map = { - SIXES: data.SIXES_DATA, - TWENTIES_1: data.TWENTIES_1_DATA, - TWENTIES_2: data.TWENTIES_2_DATA, - TWENTIES_3: data.TWENTIES_3_DATA, - } - wiring = wiring_map.get(switch_type) - if not wiring: + if switch_type not in [SIXES, TWENTIES_1, TWENTIES_2, TWENTIES_3]: raise ValueError("illegal switch type") - return SteppingSwitch(wiring, init_pos) + return SteppingSwitch(dec_wiring=data.DECRYPT_DATA[switch_type], + enc_wiring=data.ENCRYPT_DATA[switch_type], + init_pos=init_pos)
--- a/purple/tests/test_switch.py Mon Dec 02 20:58:36 2013 -0600 +++ b/purple/tests/test_switch.py Tue Dec 03 19:20:48 2013 -0600 @@ -23,10 +23,48 @@ [0, 1, 2] ] self.assertRaises(SteppingSwitchError, SteppingSwitch, bad_wiring) - self.assertRaises(SteppingSwitchError, SteppingSwitch, bad_wiring, 0) - self.assertRaises(SteppingSwitchError, SteppingSwitch, good_wiring, -1) - self.assertRaises(SteppingSwitchError, SteppingSwitch, good_wiring, 3) - self.assertRaises(SteppingSwitchError, SteppingSwitch, bad_wiring, 3) + self.assertRaises(SteppingSwitchError, SteppingSwitch, bad_wiring, + init_pos=0) + self.assertRaises(SteppingSwitchError, SteppingSwitch, good_wiring, + init_pos=-1) + self.assertRaises(SteppingSwitchError, SteppingSwitch, good_wiring, + init_pos=3) + self.assertRaises(SteppingSwitchError, SteppingSwitch, bad_wiring, + init_pos=3) + + def test_wiring_table_mismatch_in_dimensions(self): + + wiring_1 = [ + [1, 2, 0], + [2, 1, 0], + [0, 1, 2], + ] + wiring_2 = [ + [1, 2, 3, 0], + [1, 2, 3, 0], + [1, 2, 3, 0], + ] + wiring_3 = [ + [1, 2, 3, 0], + [1, 2, 3, 0], + [1, 2, 3, 0], + [1, 2, 3, 0], + ] + bad_wiring = [ + [1, 2, 0], + [2, 1], + [0, 1, 2] + ] + self.assertRaises(SteppingSwitchError, SteppingSwitch, wiring_1, + wiring_2) + self.assertRaises(SteppingSwitchError, SteppingSwitch, wiring_2, + wiring_1) + self.assertRaises(SteppingSwitchError, SteppingSwitch, wiring_1, + bad_wiring) + self.assertRaises(SteppingSwitchError, SteppingSwitch, wiring_2, + wiring_3) + self.assertRaises(SteppingSwitchError, SteppingSwitch, wiring_3, + wiring_2) def test_bad_set_pos(self):