1 from __future__
import division
3 from weakref
import ref
5 class Constraint(object):
6 """Represents any group of cells in a grid that cannot repeat a digit."""
10 # True iff a constraint consists of a straight line of cells. Used to
11 # quickly skip over pairs of constraints that cannot possibly have more
12 # than one cell in common.
15 # NOTE: _cells is a list of refs; _grid is a ref
17 cells
= property(lambda self
: [ x() for x
in self
._cells
])
18 grid
= property(lambda self
: self
._grid())
21 # XXX inherited __init__ to init _grid/_cells
23 def find_value(self
, value
):
24 """Returns the cells that can be a specific value."""
26 for cell
in self
.cells
:
27 if value
in cell
._values
:
28 possible_cells
.append(cell
)
30 if len(possible_cells
) == 0:
35 def resolve_uniques(self
):
36 """Searches for values that can only appear in one cell, and sets them
39 Returns the number of cell changes.
44 for value
in xrange(self
.grid
.size
):
45 # XXX cache values that are taken care of
46 possible_cells
= self
.find_value(value
)
48 if len(possible_cells
) > 1:
52 target_cell
= possible_cells
[0]
53 if target_cell
.solved
:
55 # XXX this is what cache is for
58 # Only cell in the group that can be value
59 cell_changes
+= target_cell
.set(value
)
64 class Box(Constraint
):
65 def _get_box_row(self
):
66 return self
._pos
// self
.grid
.box_width
67 box_row
= property(_get_box_row
)
69 def _get_box_column(self
):
70 return self
._pos % self
.grid
.box_height
71 box_column
= property(_get_box_column
)
73 def __init__(self
, grid
, position
):
74 self
._grid
= ref(grid
)
78 for row
in xrange(self
.grid
.box_height
):
79 for col
in xrange(self
.grid
.box_width
):
80 cell_row
= row
+ self
.box_row
* self
.grid
.box_height
81 cell_col
= col
+ self
.box_column
* self
.grid
.box_width
82 self
._cells
.append(ref(self
.grid
.cell(cell_row
, cell_col
)))
85 class Row(Constraint
):
88 def __init__(self
, grid
, position
):
89 self
._grid
= ref(grid
)
93 for col
in xrange(self
.grid
.size
):
94 self
._cells
.append(ref(self
.grid
.cell(self
._pos
, col
)))
96 class Column(Constraint
):
99 def __init__(self
, grid
, position
):
100 self
._grid
= ref(grid
)
104 for row
in xrange(self
.grid
.size
):
105 self
._cells
.append(ref(self
.grid
.cell(row
, self
._pos
)))
107 class Diagonal(Constraint
):
110 def __init__(self
, grid
, direction
='down', offset
=0):
111 self
._grid
= ref(grid
)
112 self
._direction
= direction
113 self
._offset
= offset
115 if direction
== 'down':
116 coords
= {'row': 0, 'column': 0}
118 elif direction
== 'up':
119 coords
= {'row': 0, 'column': grid
.size
- 1}
122 raise Exception # XXX
126 raise NotImplementedError
129 for i
in xrange(self
.grid
.size
):
130 self
._cells
.append(ref(self
.grid
.cell(coords
['row'], coords
['column'])))
132 coords
['column'] += increment