1 from operator
import attrgetter
2 from weakref
import ref
5 """Represents a single cell/value within a sudoku grid."""
10 """True iff this cell has been solved."""
11 return len(self
._values
) == 1
12 solved
= property(_get_solved
)
15 """Returns this cell's value, if it has one known."""
17 return self
._values
[0]
19 value
= property(_get_value
)
21 grid
= property(lambda self
: self
._grid())
22 constraints
= property(attrgetter('_constraints'))
24 def __init__(self
, grid
, row
, column
):
25 self
._grid
= ref(grid
)
28 self
._values
= range(self
.grid
.size
)
29 self
._constraints
= []
30 self
._normalized
= False
32 def add_constraint(self
, constraint
):
33 self
._constraints
.append(constraint
)
35 def set(self
, value
, normalize
=True):
36 """Sets the value of this cell. If `normalize` is True or omitted, the
37 grid will be updated accordingly.
39 Returns the number of cell changes.
41 self
._values
= [value
]
43 self
._normalized
= False
44 return self
.normalize() + 1
50 """If this cell has been solved, eliminates its value as a candidate
51 from every other cell in every group it's in.
52 This method is exhaustive; repeated calls should have no effect.
54 Returns the number of cell changes.
61 # Set this now just in case of infinite looping
62 self
._normalized
= True
65 # Don't know the value yet
70 for constraint
in self
.constraints
:
71 for cell
in constraint
.cells
:
74 cell_changes
+= cell
.eliminate(self
.value
)
78 def eliminate(self
, value
):
79 """Eliminates the given value as a possibility for this cell.
81 Returns the number of cell changes."""
82 if value
not in self
._values
:
85 self
._values
.remove(value
)
87 if len(self
._values
) == 0:
88 # XXX give me a real exception here
91 self
._normalized
= False
92 return self
.normalize() + 1