Added a Diagonal constraint.
[pseudoku.git] / pseudoku / grid / cellgroup.py
index 863ca4e..841a490 100644 (file)
@@ -1,16 +1,19 @@
 from __future__ import division
 
-from weakref import proxy
+from weakref import ref
 
-class CellGroup(object):
-    """Represents any group of cells in a grid."""
+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 CellGroup(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)
 
@@ -43,54 +46,66 @@ class CellGroup(object):
             target_cell.set(value)
 
 
-class Box(CellGroup):
+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(CellGroup):
-    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(CellGroup):
-    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)
-
+class Column(CellConstraint):
     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)))
+
+class Diagonal(CellConstraint):
+    def __init__(self, grid, direction='down', offset=0):
+        self._grid = ref(grid)
+        self._direction = direction
+        self._offset = offset
+
+        if direction == 'down':
+            coords = {'row': 0, 'column': 0}
+            increment = 1
+        elif direction == 'up':
+            coords = {'row': 0, 'column': grid.size - 1}
+            increment = -1
+        else:
+            raise Exception # XXX
+
+        # XXX
+        if offset != 0:
+            raise NotImplementedError
+
+        self._cells = []
+        for i in xrange(self.grid.size):
+            self._cells.append(ref(self.grid.cell(coords['row'], coords['column'])))
+            coords['row'] += 1
+            coords['column'] += increment