# HG changeset patch # User Brian Neal # Date 1340159528 18000 # Node ID f3af458a5d2d841c3a9e09d1d239d559a1649e6a # Parent 160e1bd599653363ea17766c1bc4ba8f264972cb Add methods to Plugboard to support hill-climbing. diff -r 160e1bd59965 -r f3af458a5d2d enigma/plugboard.py --- a/enigma/plugboard.py Tue Jun 19 19:02:37 2012 -0500 +++ b/enigma/plugboard.py Tue Jun 19 21:32:08 2012 -0500 @@ -8,6 +8,7 @@ """ import collections +import copy from itertools import chain import string @@ -55,6 +56,11 @@ # construct wiring mapping table with default 1-1 mappings self.wiring_map = list(range(26)) + # construct backup storage for the wiring map; this is useful when + # hill-climbing and is used when the Plugboard is used as a context + # manager + self._backup_map = list(range(26)) + # use settings if provided if not wiring_pairs: return @@ -173,3 +179,62 @@ """ return self.wiring_map[n] + + # Support for hill-climbing algorithms: + + def get_wiring(self): + """Returns a deep copy of the internal wiring map.""" + return copy.deepcopy(self.wiring_map) + + def is_wired(self, n): + """Returns True if connection n has a cable attached; 0 <= n < 26.""" + return self.wiring_map[n] != n + + def is_free(self, n): + """Returns True if connection n has no cable attached; 0 <= n < 26.""" + return self.wiring_map[n] == n + + def __enter__(self): + """Saves the current state of the wiring map.""" + for n in range(26): + self._backup_map[n] = self.wiring_map[n] + return self + + def __exit__(self, *exc_info): + """Restores the saved state of the wiring map.""" + for n in range(26): + self.wiring_map[n] = self._backup_map[n] + + def connection(self, n): + """Returns plug number [0-25] for what is connected to plug n [0-25].""" + return self.wiring_map[n] + + def disconnect(self, n): + """Removes cable from plug number n [0-25].""" + x = self.wiring_map[n] + self.wiring_map[x] = x + self.wiring_map[n] = n + + def connect(self, x, y): + """Connects plug x to plug y, removing any existing connections first. + + x and y must be in [0-25]. + + """ + # disconnect any existing connections + m = self.wiring_map[x] + n = self.wiring_map[y] + self.wiring_map[m] = m + self.wiring_map[n] = n + + self.wiring_map[x] = y + self.wiring_map[y] = x + + def is_connected(self, x, y): + """Returns True if x is connected to y. + + x and y must be in [0-25]. + + """ + return self.wiring_map[x] == y and self.wiring_map[y] == x +