From: Eevee Date: Fri, 19 Dec 2008 09:35:16 +0000 (-0800) Subject: Removed distinction between Row/Box/Column. X-Git-Url: http://git.veekun.com/pseudoku.git/commitdiff_plain/a49a2fc56c430884ad137031168836c9a3c6bfe9 Removed distinction between Row/Box/Column. CellConstraints now remember which cells they actually own, rather than generating a list on the fly. Grids are largely apathetic towards which constraints they actually have once they exist. Also swapped out proxies for ref()s and gave CellConstraint some real properties to get around the ugliness of that. --- diff --git a/pseudoku/grid/__init__.py b/pseudoku/grid/__init__.py index ce7a701..e91a1bd 100644 --- a/pseudoku/grid/__init__.py +++ b/pseudoku/grid/__init__.py @@ -35,41 +35,21 @@ class Cell(object): return None value = property(_get_value) - def _get_row(self): - """Returns the Row object associated with this cell.""" - return self._grid._rows[self._row] - row = property(_get_row) - - def _get_column(self): - """Returns the Column object associated with this cell.""" - return self._grid._columns[self._col] - column = property(_get_column) - - def _get_box(self): - """Returns the Box object associated with this cell.""" - # Some actual math required here! - # Row 0..2 -> box 0..2 - # Col 0..2 -> box 0, 3, 6 (box col 0) - box_row = self._row // self._grid._box_height - box_col = self._col // self._grid._box_width - box_idx = box_row * self._grid._box_height + box_col - return self._grid._boxes[box_idx] - box = property(_get_box) - def _get_constraints(self): - return [ self.row, self.column, self.box ] + return self._constraints constraints = property(_get_constraints) - def _get_groups(self): - return self._groups - def __init__(self, grid, row, column): self._grid = proxy(grid) self._row = row self._col = column self._values = range(self._grid.size) + self._constraints = [] self._normalized = False + def add_constraint(self, constraint): + self._constraints.append(constraint) + def set(self, value, normalize=True): """Sets the value of this cell. If `normalize` is True or omitted, the grid will be updated accordingly. @@ -99,8 +79,8 @@ class Cell(object): return # Elimination time - for group in self.constraints: - for cell in group.cells: + for constraint in self.constraints: + for cell in constraint.cells: if cell == self: continue cell.eliminate(self.value) @@ -177,7 +157,7 @@ class Grid(object): size = property(_get_size) def _get_constraints(self): - return self._rows + self._columns + self._boxes + return self._constraints constraints = property(_get_constraints) ### Constructors @@ -190,16 +170,15 @@ class Grid(object): self._box_width = box_width self._size = box_height * box_width - self._rows = [Row(self, i) for i in xrange(self._size)] - self._columns = [Column(self, i) for i in xrange(self._size)] - self._boxes = [Box(self, i) for i in xrange(self._size)] - self._cells = range(self._size ** 2) for row in xrange(self._size): for col in xrange(self._size): self._cells[self._cellidx(row, col)] \ = Cell(self, row, col) + self._constraints = [] + self.add_default_constraints() + @classmethod def from_matrix(cls, rows, box_height=None, box_width=None): """Creates and returns a grid read from a list of lists.""" @@ -259,6 +238,21 @@ class Grid(object): return self + ### Constraints + + def add_constraint(self, constraint): + self._constraints.append(constraint) + for cell in constraint.cells: + cell.add_constraint(constraint) + + def add_default_constraints(self): + for i in xrange(self._size): + self.add_constraint(Row(self, i)) + self.add_constraint(Column(self, i)) + self.add_constraint(Box(self, i)) + + return + ### Inspectors def cell(self, row, column): diff --git a/pseudoku/grid/cellgroup.py b/pseudoku/grid/cellgroup.py index 8ff948e..374bd20 100644 --- a/pseudoku/grid/cellgroup.py +++ b/pseudoku/grid/cellgroup.py @@ -1,16 +1,19 @@ from __future__ import division -from weakref import proxy +from weakref import ref class CellConstraint(object): """Represents any group of cells in a grid that cannot repeat a digit.""" ### Accessors - cells = [] + # NOTE: _cells is a list of refs; _grid is a ref + # XXX document this + cells = property(lambda self: [ x() for x in self._cells ]) + grid = property(lambda self: self._grid()) ### Methods - # XXX inherited __init__ + # XXX inherited __init__ to init _grid/_cells def find_value(self, value): """Returns the cells that can be a specific value.""" @@ -25,7 +28,7 @@ class CellConstraint(object): return possible_cells def resolve_uniques(self): - for value in xrange(self._grid._size): + for value in xrange(self.grid._size): # XXX cache values that are taken care of possible_cells = self.find_value(value) @@ -45,52 +48,39 @@ class CellConstraint(object): class Box(CellConstraint): def _get_box_row(self): - return self._pos // self._grid._box_width + return self._pos // self.grid._box_width box_row = property(_get_box_row) def _get_box_column(self): - return self._pos % self._grid._box_height + return self._pos % self.grid._box_height box_column = property(_get_box_column) - def _get_cells(self): - # XXX generator + docstring - cells = [] - for row in xrange(self._grid._box_height): - for col in xrange(self._grid._box_width): - cell_row = row + self.box_row * self._grid._box_height - cell_col = col + self.box_column * self._grid._box_width - cells.append(self._grid.cell(cell_row, cell_col)) - return cells - cells = property(_get_cells) - def __init__(self, grid, position): - self._grid = proxy(grid) + self._grid = ref(grid) self._pos = position + self._cells = [] + for row in xrange(self.grid._box_height): + for col in xrange(self.grid._box_width): + cell_row = row + self.box_row * self.grid._box_height + cell_col = col + self.box_column * self.grid._box_width + self._cells.append(ref(self.grid.cell(cell_row, cell_col))) -class Row(CellConstraint): - def _get_cells(self): - # XXX generator + docstring - cells = [] - for col in xrange(self._grid._size): - cells.append(self._grid.cell(self._pos, col)) - return cells - cells = property(_get_cells) +class Row(CellConstraint): def __init__(self, grid, position): - self._grid = proxy(grid) + self._grid = ref(grid) self._pos = position + self._cells = [] + for col in xrange(self.grid._size): + self._cells.append(ref(self.grid.cell(self._pos, col))) class Column(CellConstraint): - def _get_cells(self): - # XXX generator + docstring - cells = [] - for row in xrange(self._grid._size): - cells.append(self._grid.cell(row, self._pos)) - return cells - cells = property(_get_cells) - def __init__(self, grid, position): - self._grid = proxy(grid) + self._grid = ref(grid) self._pos = position + + self._cells = [] + for row in xrange(self.grid._size): + self._cells.append(ref(self.grid.cell(row, self._pos)))