def test_slide(): p = Tableau(""" 1 1 2 4 5 5 1 2 3 4 4 6 2 2 6 6 7 3 4 7 9 5 """) x = p.remove(2, 2) q = Tableau(""" 1 1 2 4 5 5 1 2 3 4 4 6 2 4 6 6 7 3 7 9 5 """) assert slide(x, 2, 2) == (q, 4, 4) assert extract_and_slide(p) == (q, 4, 4) assert reverse_slide(q, 4, 2) == (x, 2)
class InsertionState: def __init__(self, tableau=None, outer=None): self.tableau = Tableau() if tableau is None else tableau self.outer = outer self.inner_dimensions = self._get_inner_dimensions() def _get_inner_dimensions(self): if self.outer: i, j = self.outer t = self.tableau.remove(i, j) else: t = self.tableau m, n = t.max_row(), t.max_column() if self.outer: i, j = self.outer assert {True, False} == {m + 2 == i, n + 2 == j} return m, n def __eq__(self, other): assert type(other) == type(self) return self.tableau == other.tableau and self.outer == other.outer def __hash__(self): return hash((self.tableau, self.outer)) def __repr__(self): return str(self.tableau) def __contains__(self, box): return box in self.tableau def __iter__(self): return self.tableau.__iter__() @property def boxes(self): return self.tableau.boxes def is_initial(self): return self.outer is not None and self.outer[0] == 1 def is_terminal(self): return self.outer is None def get(self, i, j, default=None): return self.tableau.get(i, j, default) def add(self, a): assert self.outer is None n = self.tableau.max_column() + 2 tableau = self.tableau.add(1, n, a) outer = (1, n) return self.__class__(tableau, outer) def has_outer_box_in_last_row(self): return self.outer and self.outer[0] == self.inner_dimensions[0] + 2 def has_outer_box_in_last_column(self): return self.outer and self.outer[1] == self.inner_dimensions[1] + 2 def pop(self): """ Returns pair (t, v) where t is the tableau formed by removing the outer box and v is value in the outer box. Raises exception if state is terminal. """ assert self.outer is not None i, j = self.outer return self.tableau.remove(i, j), self.get(i, j) def next(self): raise NotImplementedError def path(self): state = self while True: next_state, bumped = state.next() if bumped is None: return yield next_state, bumped state = next_state def insert(self, a): assert self.is_terminal() state = self.add(a) path = list(state.path()) bumping_path = [box for _, box in path] final_state = path[-1][0] return final_state, bumping_path