9
9
10
10
11
11
def cross (items_a , items_b ):
12
- "Cross product of elements in A and elements in B."
12
+ """
13
+ Cross product of elements in A and elements in B.
14
+ """
13
15
return [a + b for a in items_a for b in items_b ]
14
16
15
17
@@ -27,7 +29,7 @@ def cross(items_a, items_b):
27
29
28
30
29
31
def test ():
30
- "A set of unit tests."
32
+ """ A set of unit tests."" "
31
33
assert len (squares ) == 81
32
34
assert len (unitlist ) == 27
33
35
assert all (len (units [s ]) == 3 for s in squares )
@@ -47,8 +49,10 @@ def test():
47
49
48
50
49
51
def parse_grid (grid ):
50
- """Convert grid to a dict of possible values, {square: digits}, or
51
- return False if a contradiction is detected."""
52
+ """
53
+ Convert grid to a dict of possible values, {square: digits}, or
54
+ return False if a contradiction is detected.
55
+ """
52
56
## To start, every square can be any digit; then assign values from the grid.
53
57
values = {s : digits for s in squares }
54
58
for s , d in grid_values (grid ).items ():
@@ -58,15 +62,19 @@ def parse_grid(grid):
58
62
59
63
60
64
def grid_values (grid ):
61
- "Convert grid into a dict of {square: char} with '0' or '.' for empties."
65
+ """
66
+ Convert grid into a dict of {square: char} with '0' or '.' for empties.
67
+ """
62
68
chars = [c for c in grid if c in digits or c in "0." ]
63
69
assert len (chars ) == 81
64
70
return dict (zip (squares , chars ))
65
71
66
72
67
73
def assign (values , s , d ):
68
- """Eliminate all the other values (except d) from values[s] and propagate.
69
- Return values, except return False if a contradiction is detected."""
74
+ """
75
+ Eliminate all the other values (except d) from values[s] and propagate.
76
+ Return values, except return False if a contradiction is detected.
77
+ """
70
78
other_values = values [s ].replace (d , "" )
71
79
if all (eliminate (values , s , d2 ) for d2 in other_values ):
72
80
return values
@@ -75,8 +83,10 @@ def assign(values, s, d):
75
83
76
84
77
85
def eliminate (values , s , d ):
78
- """Eliminate d from values[s]; propagate when values or places <= 2.
79
- Return values, except return False if a contradiction is detected."""
86
+ """
87
+ Eliminate d from values[s]; propagate when values or places <= 2.
88
+ Return values, except return False if a contradiction is detected.
89
+ """
80
90
if d not in values [s ]:
81
91
return values ## Already eliminated
82
92
values [s ] = values [s ].replace (d , "" )
@@ -99,7 +109,9 @@ def eliminate(values, s, d):
99
109
100
110
101
111
def display (values ):
102
- "Display these values as a 2-D grid."
112
+ """
113
+ Display these values as a 2-D grid.
114
+ """
103
115
width = 1 + max (len (values [s ]) for s in squares )
104
116
line = "+" .join (["-" * (width * 3 )] * 3 )
105
117
for r in rows :
@@ -114,19 +126,24 @@ def display(values):
114
126
115
127
116
128
def solve (grid ):
129
+ """
130
+ Solve the grid.
131
+ """
117
132
return search (parse_grid (grid ))
118
133
119
134
120
135
def some (seq ):
121
- "Return some element of seq that is true."
136
+ """ Return some element of seq that is true."" "
122
137
for e in seq :
123
138
if e :
124
139
return e
125
140
return False
126
141
127
142
128
143
def search (values ):
129
- "Using depth-first search and propagation, try all possible values."
144
+ """
145
+ Using depth-first search and propagation, try all possible values.
146
+ """
130
147
if values is False :
131
148
return False ## Failed earlier
132
149
if all (len (values [s ]) == 1 for s in squares ):
@@ -137,9 +154,11 @@ def search(values):
137
154
138
155
139
156
def solve_all (grids , name = "" , showif = 0.0 ):
140
- """Attempt to solve a sequence of grids. Report results.
157
+ """
158
+ Attempt to solve a sequence of grids. Report results.
141
159
When showif is a number of seconds, display puzzles that take longer.
142
- When showif is None, don't display any puzzles."""
160
+ When showif is None, don't display any puzzles.
161
+ """
143
162
144
163
def time_solve (grid ):
145
164
start = time .monotonic ()
@@ -162,7 +181,9 @@ def time_solve(grid):
162
181
163
182
164
183
def solved (values ):
165
- "A puzzle is solved if each unit is a permutation of the digits 1 to 9."
184
+ """
185
+ A puzzle is solved if each unit is a permutation of the digits 1 to 9.
186
+ """
166
187
167
188
def unitsolved (unit ):
168
189
return {values [s ] for s in unit } == set (digits )
@@ -177,9 +198,11 @@ def from_file(filename, sep="\n"):
177
198
178
199
179
200
def random_puzzle (assignments = 17 ):
180
- """Make a random puzzle with N or more assignments. Restart on contradictions.
201
+ """
202
+ Make a random puzzle with N or more assignments. Restart on contradictions.
181
203
Note the resulting puzzle is not guaranteed to be solvable, but empirically
182
- about 99.8% of them are solvable. Some have multiple solutions."""
204
+ about 99.8% of them are solvable. Some have multiple solutions.
205
+ """
183
206
values = {s : digits for s in squares }
184
207
for s in shuffled (squares ):
185
208
if not assign (values , s , random .choice (values [s ])):
@@ -191,7 +214,9 @@ def random_puzzle(assignments=17):
191
214
192
215
193
216
def shuffled (seq ):
194
- "Return a randomly shuffled copy of the input sequence."
217
+ """
218
+ Return a randomly shuffled copy of the input sequence.
219
+ """
195
220
seq = list (seq )
196
221
random .shuffle (seq )
197
222
return seq
0 commit comments