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._constraints
+ constraints = property(_get_constraints)
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_type in 'row', 'column', 'box':
- group = getattr(self, group_type)
- for cell in group.cells:
+ for constraint in self.constraints:
+ for cell in constraint.cells:
if cell == self:
continue
cell.eliminate(self.value)
return self._size
size = property(_get_size)
- def _get_cell_groups(self):
- return self._rows + self._columns + self._boxes
- cell_groups = property(_get_cell_groups)
+ def _get_constraints(self):
+ 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):
self.normalize_cells()
# Step 1: Find values that can only go in one cell in a group
- for group in self.cell_groups:
+ for group in self.constraints:
group.resolve_uniques()