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.
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)
size = property(_get_size)
def _get_constraints(self):
- return self._rows + self._columns + self._boxes
+ return self._constraints
constraints = property(_get_constraints)
### Constructors
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."""
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):
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."""
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)
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)))