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 """Checks to see if this cell has only one possible value left. If
51 so, sets that as its value and eliminates it from every related cell.
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