Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/games/sudoku.py
4079 views
1
r"""
2
Sudoku Puzzles
3
4
This module provides algorithms to solve Sudoku puzzles, plus tools
5
for inputting, converting and displaying various ways of writing a
6
puzzle or its solution(s). Primarily this is accomplished with the
7
:class:`sage.games.sudoku.Sudoku` class, though the legacy top-level
8
:func:`sage.games.sudoku.sudoku` function is also available.
9
10
AUTHORS:
11
12
- Tom Boothby (2008/05/02): Exact Cover, Dancing Links algorithm
13
- Robert Beezer (2009/05/29): Backtracking algorithm, Sudoku class
14
"""
15
######################################################################
16
# Copyright (C) 2009, Robert A. Beezer <[email protected]>
17
#
18
# Distributed under the terms of the GNU General Public License (GPL)
19
#
20
# The full text of the GPL is available at:
21
# http://www.gnu.org/licenses/
22
######################################################################
23
24
from sage.structure.sage_object import SageObject
25
26
def sudoku(m):
27
r"""
28
Solves Sudoku puzzles described by matrices.
29
30
INPUT:
31
32
- ``m`` - a square Sage matrix over `\ZZ`, where zeros are blank entries
33
34
OUTPUT:
35
36
A Sage matrix over `\ZZ` containing the first solution found,
37
otherwise ``None``.
38
39
This function matches the behavior of the prior Sudoku solver
40
and is included only to replicate that behavior. It could be
41
safely deprecated, since all of its functionality is included in the :class:`~sage.games.sudoku.Sudoku` class.
42
43
EXAMPLE:
44
45
An example that was used in previous doctests. ::
46
47
sage: A = matrix(ZZ,9,[5,0,0, 0,8,0, 0,4,9, 0,0,0, 5,0,0, 0,3,0, 0,6,7, 3,0,0, 0,0,1, 1,5,0, 0,0,0, 0,0,0, 0,0,0, 2,0,8, 0,0,0, 0,0,0, 0,0,0, 0,1,8, 7,0,0, 0,0,4, 1,5,0, 0,3,0, 0,0,2, 0,0,0, 4,9,0, 0,5,0, 0,0,3])
48
sage: A
49
[5 0 0 0 8 0 0 4 9]
50
[0 0 0 5 0 0 0 3 0]
51
[0 6 7 3 0 0 0 0 1]
52
[1 5 0 0 0 0 0 0 0]
53
[0 0 0 2 0 8 0 0 0]
54
[0 0 0 0 0 0 0 1 8]
55
[7 0 0 0 0 4 1 5 0]
56
[0 3 0 0 0 2 0 0 0]
57
[4 9 0 0 5 0 0 0 3]
58
sage: sudoku(A)
59
[5 1 3 6 8 7 2 4 9]
60
[8 4 9 5 2 1 6 3 7]
61
[2 6 7 3 4 9 5 8 1]
62
[1 5 8 4 6 3 9 7 2]
63
[9 7 4 2 1 8 3 6 5]
64
[3 2 6 7 9 5 4 1 8]
65
[7 8 2 9 3 4 1 5 6]
66
[6 3 5 1 7 2 8 9 4]
67
[4 9 1 8 5 6 7 2 3]
68
69
Using inputs that are possible with the
70
:class:`~sage.games.sudoku.Sudoku` class,
71
other than a matrix, will cause an error. ::
72
73
sage: sudoku('.4..32....14..3.')
74
Traceback (most recent call last):
75
...
76
ValueError: sudoku function expects puzzle to be a matrix, perhaps use the Sudoku class
77
"""
78
from sage.matrix.matrix import Matrix
79
80
if not(isinstance(m, Matrix)):
81
raise ValueError('sudoku function expects puzzle to be a matrix, perhaps use the Sudoku class')
82
solution = Sudoku(m).solve(algorithm='dlx').next()
83
return (solution.to_matrix() if solution else None)
84
85
86
class Sudoku(SageObject):
87
r"""
88
An object representing a Sudoku puzzle. Primarily the purpose is to
89
solve the puzzle, but conversions between formats are also provided.
90
91
INPUT:
92
93
- puzzle - the first argument can take one of three forms
94
* list - a Python list with elements of the puzzle in row-major order,
95
where a blank entry is a zero
96
* matrix - a square Sage matrix over `\ZZ`
97
* string - a string where each character is an entry of
98
the puzzle. For two-digit entries, a = 10, b = 11, etc.
99
- verify_input - default = ``True``, use ``False`` if you know the input is valid
100
101
102
EXAMPLE::
103
104
sage: a = Sudoku('5...8..49...5...3..673....115..........2.8..........187....415..3...2...49..5...3')
105
sage: print a
106
+-----+-----+-----+
107
|5 | 8 | 4 9|
108
| |5 | 3 |
109
| 6 7|3 | 1|
110
+-----+-----+-----+
111
|1 5 | | |
112
| |2 8| |
113
| | | 1 8|
114
+-----+-----+-----+
115
|7 | 4|1 5 |
116
| 3 | 2| |
117
|4 9 | 5 | 3|
118
+-----+-----+-----+
119
sage: print a.solve().next()
120
+-----+-----+-----+
121
|5 1 3|6 8 7|2 4 9|
122
|8 4 9|5 2 1|6 3 7|
123
|2 6 7|3 4 9|5 8 1|
124
+-----+-----+-----+
125
|1 5 8|4 6 3|9 7 2|
126
|9 7 4|2 1 8|3 6 5|
127
|3 2 6|7 9 5|4 1 8|
128
+-----+-----+-----+
129
|7 8 2|9 3 4|1 5 6|
130
|6 3 5|1 7 2|8 9 4|
131
|4 9 1|8 5 6|7 2 3|
132
+-----+-----+-----+
133
"""
134
135
def __init__(self, puzzle, verify_input = True):
136
r"""
137
Initialize a Sudoku puzzle, determine its size, sanity-check the inputs.
138
139
TESTS::
140
sage: d = Sudoku('1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1')
141
sage: d == loads(dumps(d))
142
True
143
144
A lame attempt to construct a puzzle from a single integer::
145
146
sage: Sudoku(8)
147
Traceback (most recent call last):
148
...
149
ValueError: Sudoku puzzle must be specified as a matrix, list or string
150
151
An attempt to construct a puzzle from a non-square matrix::
152
153
sage: Sudoku(matrix(2,range(6)))
154
Traceback (most recent call last):
155
...
156
ValueError: Sudoku puzzle must be a square matrix
157
158
An attempt to construct a puzzle from a string of an impossible length (9)::
159
160
sage: Sudoku('.........')
161
Traceback (most recent call last):
162
...
163
ValueError: Sudoku puzzle dimension of 3 must be a perfect square
164
165
An attempt to construct a `4\times 4` puzzle from a string with a bad entry (5)::
166
167
sage: Sudoku('.1.2.......5....')
168
Traceback (most recent call last):
169
...
170
ValueError: Sudoku puzzle has an invalid entry
171
"""
172
from math import sqrt
173
from sage.matrix.matrix import Matrix
174
175
if isinstance(puzzle, list):
176
puzzle_size = int(round(sqrt(len(puzzle))))
177
self.puzzle = tuple(puzzle)
178
elif isinstance(puzzle, Matrix):
179
puzzle_size = puzzle.ncols()
180
if verify_input and not(puzzle.is_square()):
181
raise ValueError('Sudoku puzzle must be a square matrix')
182
self.puzzle = tuple([int(x) for x in puzzle.list()])
183
elif isinstance(puzzle, basestring):
184
puzzle_size = int(round(sqrt(len(puzzle))))
185
puzzle_numeric = []
186
for char in puzzle:
187
if char.isdigit():
188
puzzle_numeric.append(int(char))
189
elif char == '.':
190
puzzle_numeric.append(0)
191
else:
192
puzzle_numeric.append(ord(char.upper()) - ord('A')+10)
193
self.puzzle = tuple(puzzle_numeric)
194
else:
195
raise ValueError('Sudoku puzzle must be specified as a matrix, list or string')
196
self.n = int(sqrt(puzzle_size))
197
if verify_input:
198
if self.n**4 != len(self.puzzle):
199
raise ValueError('Sudoku puzzle dimension of %s must be a perfect square' % puzzle_size)
200
for x in self.puzzle:
201
if (x < 0) or (x > self.n*self.n):
202
raise ValueError('Sudoku puzzle has an invalid entry')
203
204
205
def __cmp__(self, other):
206
r"""
207
Compares two Sudoku puzzles, based on the underlying
208
representation of the puzzles as tuples.
209
210
A puzzle with fewer entries is considered less than a
211
puzzle with more entries. For two puzzles of the same
212
size, their entries are compared lexicographically
213
based on a row-major order. Since blank entries are
214
carried as zeros, progressively "more completed" puzzles
215
are considered larger (but this is not an equivalence).
216
217
EXAMPLES::
218
219
sage: a = Sudoku('.4..32....14..3.')
220
sage: b = Sudoku('8..6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......')
221
sage: c = Sudoku('1..6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......')
222
sage: d = Sudoku('81.6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......')
223
sage: a.__cmp__(b)
224
-1
225
sage: b.__cmp__(b)
226
0
227
sage: b.__cmp__(c)
228
1
229
sage: b.__cmp__(d)
230
-1
231
"""
232
left = self.puzzle
233
right = tuple(other.to_list())
234
if left < right:
235
return -1
236
elif left > right:
237
return 1
238
else:
239
return 0
240
241
242
def _repr_(self):
243
r"""
244
Returns a concise description of a Sudoku puzzle using a string representation.
245
246
See the docstring for :func:`to_ascii` for more information on the format.
247
248
EXAMPLE::
249
250
sage: s = Sudoku('.4..32....14..3.')
251
sage: s._repr_()
252
'+---+---+\n| 4| |\n|3 2| |\n+---+---+\n| |1 4|\n| |3 |\n+---+---+'
253
254
"""
255
return self.to_ascii()
256
257
def _latex_(self):
258
r"""nodetex
259
Returns a `\mbox{\rm\LaTeX}` representation of a Sudoku puzzle as an array environment.
260
261
EXAMPLE::
262
263
sage: s = Sudoku('.4..32....14..3.')
264
sage: s._latex_()
265
'\\begin{array}{|*{2}{*{2}{r}|}}\\hline\n &4& & \\\\\n3&2& & \\\\\\hline\n & &1&4\\\\\n & &3& \\\\\\hline\n\\end{array}'
266
"""
267
return self.to_latex()
268
269
def _matrix_(self, R=None):
270
r"""
271
Returns the puzzle as a matrix to support Sage's
272
:func:`~sage.matrix.constructor.matrix` constructor.
273
274
The base ring will be `\ZZ` if ``None`` is provided,
275
and it is an error to specify any other base ring.
276
277
EXAMPLE::
278
279
sage: k = Sudoku('.4..32....14..3.')
280
sage: matrix(k) # indirect doctest
281
[0 4 0 0]
282
[3 2 0 0]
283
[0 0 1 4]
284
[0 0 3 0]
285
sage: matrix(ZZ,k)
286
[0 4 0 0]
287
[3 2 0 0]
288
[0 0 1 4]
289
[0 0 3 0]
290
sage: matrix(QQ,k)
291
Traceback (most recent call last):
292
...
293
ValueError: Sudoku puzzles only convert to matrices over Integer Ring, not Rational Field
294
"""
295
from sage.rings.integer_ring import ZZ, IntegerRing_class
296
if R and not(isinstance(R, IntegerRing_class)):
297
raise ValueError('Sudoku puzzles only convert to matrices over %s, not %s' % (ZZ, R))
298
return self.to_matrix()
299
300
def to_string(self):
301
r"""
302
Constructs a string representing a Sudoku puzzle.
303
304
Blank entries are represented as periods, single
305
digits are not converted and two digit entries are
306
converted to lower-case letters where ``10 = a``,
307
``11 = b``, etc. This scheme limits puzzles to
308
at most 36 symbols.
309
310
EXAMPLE::
311
312
sage: b = matrix(ZZ, 9, 9, [ [0,0,0,0,1,0,9,0,0], [8,0,0,4,0,0,0,0,0], [2,0,0,0,0,0,0,0,0], [0,7,0,0,3,0,0,0,0], [0,0,0,0,0,0,2,0,4], [0,0,0,0,0,0,0,5,8], [0,6,0,0,0,0,1,3,0], [7,0,0,2,0,0,0,0,0], [0,0,0,8,0,0,0,0,0] ])
313
sage: Sudoku(b).to_string()
314
'....1.9..8..4.....2.........7..3..........2.4.......58.6....13.7..2........8.....'
315
316
TESTS:
317
318
This tests the conversion of alphabetic characters as well as the
319
input and output of Sudoku puzzles as strings. ::
320
321
sage: j = Sudoku([0, 0, 0, 0, 10, 0, 0, 6, 9, 0, 3, 0, 0, 0, 0, 1, 13, 0, 2, 0, 0, 0, 8, 0, 0, 0, 0, 14, 0, 4, 0, 0, 0, 0, 11, 0, 0, 0, 0, 5, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 15, 0, 0, 0, 0, 1, 0, 14, 0, 0, 2, 0, 11, 0, 8, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 13, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 7, 0, 16, 0, 0, 9, 0, 10, 0, 0, 12, 0, 0, 0, 5, 0, 0, 0, 0, 0, 8, 0, 0, 15, 0, 0, 0, 0, 0, 1, 0, 0, 14, 0, 7, 9, 0, 12, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 16, 0, 7, 0, 0, 0, 0, 0, 0, 8, 4, 0, 0, 0, 0, 3, 0, 13, 0, 0, 10, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 14, 0, 0, 0, 12, 10, 0, 0, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 4, 0, 0, 0, 13, 0, 0, 14, 0, 0, 16, 0, 9, 2, 0, 6, 0, 0, 8, 0, 0, 0, 0])
322
sage: st = j.to_string()
323
sage: st
324
'....a..69.3....1d.2...8....e.4....b....5..c.......7.......g...f....1.e..2.b.8..3.......4.d.....6.........f..7.g..9.a..c...5.....8..f.....1..e.79.c....b.....2...6.....g.7......84....3.d..a.5....5...7..e...ca.....3.1.......b......f....4...d..e..g.92.6..8....'
325
sage: st == Sudoku(st).to_string()
326
True
327
328
A `49\times 49` puzzle with all entries equal to 40,
329
which doesn't convert to a letter. ::
330
331
sage: empty = [40]*2401
332
sage: Sudoku(empty).to_string()
333
Traceback (most recent call last):
334
...
335
ValueError: Sudoku string representation is only valid for puzzles of size 36 or smaller
336
"""
337
encoded = []
338
for x in self.puzzle:
339
if x == 0:
340
encoded.append('.')
341
elif 1 <= x <= 9:
342
encoded.append(str(x))
343
elif x <= 36:
344
encoded.append(chr(x-10+ord('a')))
345
else:
346
raise ValueError('Sudoku string representation is only valid for puzzles of size 36 or smaller')
347
return ''.join(encoded)
348
349
350
def to_list(self):
351
r"""
352
Constructs a list representing a Sudoku puzzle, in row-major order.
353
354
EXAMPLE::
355
356
sage: s = Sudoku('1.......2.9.4...5...6...7...5.9.3.......7.......85..4.7.....6...3...9.8...2.....1')
357
sage: print s.to_list()
358
[1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 9, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 5, 0, 9, 0, 3, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 5, 0, 0, 4, 0, 7, 0, 0, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 9, 0, 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1]
359
360
TEST:
361
362
This tests the input and output of Sudoku puzzles as lists. ::
363
364
sage: alist = [0, 4, 0, 0, 3, 2, 0, 0, 0, 0, 1, 4, 0, 0, 3, 0]
365
sage: alist == Sudoku(alist).to_list()
366
True
367
"""
368
return list(self.puzzle)
369
370
371
def to_matrix(self):
372
r"""
373
Constructs a Sage matrix over `\ZZ` representing a Sudoku puzzle.
374
375
EXAMPLES::
376
377
sage: s = Sudoku('.4..32....14..3.')
378
sage: s.to_matrix()
379
[0 4 0 0]
380
[3 2 0 0]
381
[0 0 1 4]
382
[0 0 3 0]
383
384
TEST:
385
386
This tests the input and output of Sudoku puzzles as matrices over `\ZZ`. ::
387
388
sage: g = matrix(ZZ, 9, 9, [ [1,0,0,0,0,7,0,9,0], [0,3,0,0,2,0,0,0,8], [0,0,9,6,0,0,5,0,0], [0,0,5,3,0,0,9,0,0], [0,1,0,0,8,0,0,0,2], [6,0,0,0,0,4,0,0,0], [3,0,0,0,0,0,0,1,0], [0,4,0,0,0,0,0,0,7], [0,0,7,0,0,0,3,0,0] ])
389
sage: g == Sudoku(g).to_matrix()
390
True
391
"""
392
from sage.rings.integer_ring import ZZ
393
from sage.matrix.constructor import matrix
394
return matrix(ZZ, self.n*self.n, self.puzzle)
395
396
397
def to_ascii(self):
398
r"""
399
Constructs an ASCII-art version of a Sudoku puzzle.
400
This is a modified version of the ASCII version of a subdivided matrix.
401
402
EXAMPLE::
403
404
sage: s = Sudoku('.4..32....14..3.')
405
sage: print s.to_ascii()
406
+---+---+
407
| 4| |
408
|3 2| |
409
+---+---+
410
| |1 4|
411
| |3 |
412
+---+---+
413
sage: s.to_ascii()
414
'+---+---+\n| 4| |\n|3 2| |\n+---+---+\n| |1 4|\n| |3 |\n+---+---+'
415
"""
416
from re import compile
417
n = self.n
418
nsquare = n*n
419
m = self.to_matrix()
420
m.subdivide(range(0,nsquare+1,n), range(0,nsquare+1,n))
421
naked_zero = compile('([\|, ]+)0')
422
blanked = naked_zero.sub(lambda x: x.group(1)+' ', m.str())
423
brackets = compile('[\[,\]]')
424
return brackets.sub('', blanked)
425
426
427
def to_latex(self):
428
r"""
429
Creates a string of `\mbox{\rm\LaTeX}` code representing a Sudoku puzzle or solution.
430
431
EXAMPLE::
432
433
sage: s = Sudoku('.4..32....14..3.')
434
sage: print s.to_latex()
435
\begin{array}{|*{2}{*{2}{r}|}}\hline
436
&4& & \\
437
3&2& & \\\hline
438
& &1&4\\
439
& &3& \\\hline
440
\end{array}
441
442
TEST::
443
444
sage: s = Sudoku('.4..32....14..3.')
445
sage: s.to_latex()
446
'\\begin{array}{|*{2}{*{2}{r}|}}\\hline\n &4& & \\\\\n3&2& & \\\\\\hline\n & &1&4\\\\\n & &3& \\\\\\hline\n\\end{array}'
447
"""
448
n = self.n
449
nsquare = n*n
450
array = []
451
array.append('\\begin{array}{|*{%s}{*{%s}{r}|}}\\hline\n' % (n, n))
452
gen = (x for x in self.puzzle)
453
for row in range(nsquare):
454
for col in range(nsquare):
455
entry = gen.next()
456
array.append((str(entry) if entry else ' '))
457
array.append(('' if col == nsquare - 1 else '&'))
458
array.append(('\\\\\n' if (row+1) % n else '\\\\\\hline\n'))
459
array.append('\\end{array}')
460
return ''.join(array)
461
462
463
def solve(self, algorithm = 'dlx'):
464
r"""
465
Returns a generator object for the solutions of a Sudoku puzzle.
466
467
INPUT:
468
469
- algorithm - default = ``'dlx'``, specify choice of solution algorithm. The
470
two possible algorithms are ``'dlx'`` and ``'backtrack'``.
471
472
OUTPUT:
473
474
A generator that provides all solutions, as objects of
475
the :class:`~sage.games.sudoku.Sudoku` class.
476
477
Calling ``next()`` on the returned generator just once will find
478
a solution, presuming it exists, otherwise it will return a
479
``StopIteration`` exception. The generator may be used for
480
iteration or wrapping the generator with ``list()`` will return
481
all of the solutions as a list. Solutions are returned as
482
new objects of the :class:`~sage.games.sudoku.Sudoku` class,
483
so may be printed or converted using other methods in this class.
484
485
Generally, the DLX algorithm is very fast and very consistent.
486
The backtrack algorithm is very variable in its performance,
487
on some occasions markedly faster than DLX but usually slower
488
by a similar factor, with the potential to be orders of magnitude
489
slower. See the docstrings for the
490
:meth:`~sage.games.sudoku.Sudoku.dlx` and
491
:meth:`~sage.games.sudoku.Sudoku.backtrack_all`
492
methods for further discussions and examples of performance.
493
Note that the backtrack algorithm is limited to puzzles of
494
size `16\times 16` or smaller.
495
496
EXAMPLES:
497
498
This puzzle has 5 solutions, but the first one returned by each algorithm are identical. ::
499
500
sage: h = Sudoku('8..6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......')
501
sage: h
502
+-----+-----+-----+
503
|8 |6 |9 5|
504
| | | |
505
| | 2 |3 1 |
506
+-----+-----+-----+
507
| 7|3 1 8| 6 |
508
|2 4 | | 7 3|
509
| | | |
510
+-----+-----+-----+
511
| 2|7 9 |1 |
512
|5 | 8 | 3 6|
513
| 3| | |
514
+-----+-----+-----+
515
sage: h.solve(algorithm='backtrack').next()
516
+-----+-----+-----+
517
|8 1 4|6 3 7|9 2 5|
518
|3 2 5|1 4 9|6 8 7|
519
|7 9 6|8 2 5|3 1 4|
520
+-----+-----+-----+
521
|9 5 7|3 1 8|4 6 2|
522
|2 4 1|9 5 6|8 7 3|
523
|6 3 8|2 7 4|5 9 1|
524
+-----+-----+-----+
525
|4 6 2|7 9 3|1 5 8|
526
|5 7 9|4 8 1|2 3 6|
527
|1 8 3|5 6 2|7 4 9|
528
+-----+-----+-----+
529
sage: h.solve(algorithm='dlx').next()
530
+-----+-----+-----+
531
|8 1 4|6 3 7|9 2 5|
532
|3 2 5|1 4 9|6 8 7|
533
|7 9 6|8 2 5|3 1 4|
534
+-----+-----+-----+
535
|9 5 7|3 1 8|4 6 2|
536
|2 4 1|9 5 6|8 7 3|
537
|6 3 8|2 7 4|5 9 1|
538
+-----+-----+-----+
539
|4 6 2|7 9 3|1 5 8|
540
|5 7 9|4 8 1|2 3 6|
541
|1 8 3|5 6 2|7 4 9|
542
+-----+-----+-----+
543
544
Gordon Royle maintains a list of 48072 Sudoku puzzles that each has
545
a unique solution and exactly 17 "hints" (initially filled boxes).
546
At this writing (May 2009) there is no known 16-hint puzzle with
547
exactly one solution. [sudoku:royle]_ This puzzle is number 3000
548
in his database. We solve it twice. ::
549
550
sage: b = Sudoku('8..6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......')
551
sage: b.solve(algorithm='dlx').next() == b.solve(algorithm='backtrack').next()
552
True
553
554
555
These are the first 10 puzzles in a list of "Top 95" puzzles,
556
[sudoku:top95]_ which we use to show that the two available algorithms obtain
557
the same solution for each. ::
558
559
sage: top =['4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......',\
560
'52...6.........7.13...........4..8..6......5...........418.........3..2...87.....',\
561
'6.....8.3.4.7.................5.4.7.3..2.....1.6.......2.....5.....8.6......1....',\
562
'48.3............71.2.......7.5....6....2..8.............1.76...3.....4......5....',\
563
'....14....3....2...7..........9...3.6.1.............8.2.....1.4....5.6.....7.8...',\
564
'......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.',\
565
'6.2.5.........3.4..........43...8....1....2........7..5..27...........81...6.....',\
566
'.524.........7.1..............8.2...3.....6...9.5.....1.6.3...........897........',\
567
'6.2.5.........4.3..........43...8....1....2........7..5..27...........81...6.....',\
568
'.923.........8.1...........1.7.4...........658.........6.5.2...4.....7.....9.....']
569
sage: p = [Sudoku(top[i]) for i in range(10)]
570
sage: verify = [p[i].solve(algorithm='dlx').next() == p[i].solve(algorithm='backtrack').next() for i in range(10)]
571
sage: verify == [True]*10
572
True
573
574
TESTS:
575
576
A `25\times 25` puzzle that the backtrack algorithm is not equipped to handle. Since ``solve`` returns a generator this test will not go boom until we ask for a solution with ``next``. ::
577
578
sage: too_big = Sudoku([0]*625)
579
sage: too_big.solve(algorithm='backtrack').next()
580
Traceback (most recent call last):
581
...
582
ValueError: The Sudoku backtrack algorithm is limited to puzzles of size 16 or smaller.
583
584
An attempt to use a non-existent algorithm. ::
585
586
sage: Sudoku([0]).solve(algorithm='bogus').next()
587
Traceback (most recent call last):
588
...
589
NotImplementedError: bogus is not an algorithm for Sudoku puzzles
590
591
.. rubric:: Citations
592
593
.. [sudoku:top95] "95 Hard Puzzles",
594
http://magictour.free.fr/top95, or http://norvig.com/top95.txt
595
.. [sudoku:royle] Gordon Royle, "Minimum Sudoku",
596
http://people.csse.uwa.edu.au/gordon/sudokumin.php
597
"""
598
if algorithm == 'backtrack':
599
if self.n > 4:
600
raise ValueError('The Sudoku backtrack algorithm is limited to puzzles of size 16 or smaller.')
601
else:
602
gen = self.backtrack()
603
elif algorithm == 'dlx':
604
gen = self.dlx()
605
else:
606
raise NotImplementedError('%s is not an algorithm for Sudoku puzzles' % algorithm)
607
for soln in gen:
608
yield Sudoku(soln, verify_input = 'False')
609
610
611
def backtrack(self):
612
r"""
613
Returns a generator which iterates through all solutions of a Sudoku puzzle.
614
615
This function is intended to be called from the
616
:func:`~sage.games.sudoku.Sudoku.solve` method
617
when the ``algorithm='backtrack'`` option is specified.
618
However it may be called directly as a method of an
619
instance of a Sudoku puzzle.
620
621
At this point, this method calls
622
:func:`~sage.games.sudoku_backtrack.backtrack_all` which
623
constructs *all* of the solutions as a list. Then the
624
present method just returns the items of the list one at
625
a time. Once Cython supports closures and a yield statement
626
is supported, then the contents of ``backtrack_all()``
627
may be subsumed into this method and the
628
:mod:`sage.games.sudoku_backtrack` module can be removed.
629
630
This routine can have wildly variable performance, with a
631
factor of 4000 observed between the fastest and slowest
632
`9\times 9` examples tested. Examples designed to perform
633
poorly for naive backtracking, will do poorly
634
(such as ``d`` below). However, examples meant to be
635
difficult for humans often do very well, with a factor
636
of 5 improvement over the `DLX` algorithm.
637
638
Without dynamically allocating arrays in the Cython version,
639
we have limited this function to `16\times 16` puzzles.
640
Algorithmic details are in the
641
:mod:`sage.games.sudoku_backtrack` module.
642
643
EXAMPLES:
644
645
This example was reported to be very difficult for human solvers.
646
This algorithm works very fast on it, at about half the time
647
of the DLX solver. [sudoku:escargot]_ ::
648
649
sage: g = Sudoku('1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..')
650
sage: print g
651
+-----+-----+-----+
652
|1 | 7| 9 |
653
| 3 | 2 | 8|
654
| 9|6 |5 |
655
+-----+-----+-----+
656
| 5|3 |9 |
657
| 1 | 8 | 2|
658
|6 | 4| |
659
+-----+-----+-----+
660
|3 | | 1 |
661
| 4 | | 7|
662
| 7| |3 |
663
+-----+-----+-----+
664
sage: print g.solve(algorithm='backtrack').next()
665
+-----+-----+-----+
666
|1 6 2|8 5 7|4 9 3|
667
|5 3 4|1 2 9|6 7 8|
668
|7 8 9|6 4 3|5 2 1|
669
+-----+-----+-----+
670
|4 7 5|3 1 2|9 8 6|
671
|9 1 3|5 8 6|7 4 2|
672
|6 2 8|7 9 4|1 3 5|
673
+-----+-----+-----+
674
|3 5 6|4 7 8|2 1 9|
675
|2 4 1|9 3 5|8 6 7|
676
|8 9 7|2 6 1|3 5 4|
677
+-----+-----+-----+
678
679
This example has no entries in the top row and a half,
680
and the top row of the solution is ``987654321`` and
681
therefore a backtracking approach is slow, taking about
682
750 times as long as the DLX solver. [sudoku:wikipedia]_ ::
683
684
sage: c = Sudoku('..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9')
685
sage: print c
686
+-----+-----+-----+
687
| | | |
688
| | 3| 8 5|
689
| 1| 2 | |
690
+-----+-----+-----+
691
| |5 7| |
692
| 4| |1 |
693
| 9 | | |
694
+-----+-----+-----+
695
|5 | | 7 3|
696
| 2| 1 | |
697
| | 4 | 9|
698
+-----+-----+-----+
699
sage: print c.solve(algorithm='backtrack').next()
700
+-----+-----+-----+
701
|9 8 7|6 5 4|3 2 1|
702
|2 4 6|1 7 3|9 8 5|
703
|3 5 1|9 2 8|7 4 6|
704
+-----+-----+-----+
705
|1 2 8|5 3 7|6 9 4|
706
|6 3 4|8 9 2|1 5 7|
707
|7 9 5|4 6 1|8 3 2|
708
+-----+-----+-----+
709
|5 1 9|2 8 6|4 7 3|
710
|4 7 2|3 1 9|5 6 8|
711
|8 6 3|7 4 5|2 1 9|
712
+-----+-----+-----+
713
714
.. rubric:: Citations
715
716
.. [sudoku:escargot] "Al Escargot", due to Arto Inkala, http://timemaker.blogspot.com/2006/12/ai-escargot-vwv.html
717
.. [sudoku:wikipedia] "Near worst case", Wikipedia: "Algorithmics of sudoku", http://en.wikipedia.org/wiki/Algorithmics_of_sudoku
718
"""
719
from sudoku_backtrack import backtrack_all
720
solutions = backtrack_all(self.n, self.puzzle)
721
for soln in solutions:
722
yield soln
723
724
725
def dlx(self, count_only=False):
726
r"""
727
Returns a generator that iterates through all solutions of a Sudoku puzzle.
728
729
INPUT:
730
731
- count_only - boolean, default = False.
732
If set to ``True`` the generator returned as output will
733
simply generate ``None`` for each solution, so the
734
calling routine can count these.
735
736
OUTPUT:
737
738
Returns a generator that that iterates over all the solutions.
739
740
This function is intended to be called from the
741
:func:`~sage.games.sudoku.Sudoku.solve` method
742
with the ``algorithm='dlx'`` option. However it
743
may be called directly as a method of an instance
744
of a Sudoku puzzle if speed is important and you
745
do not need automatic conversions on the output
746
(or even just want to count solutions without looking
747
at them). In this case, inputting a puzzle as a list,
748
with ``verify_input=False`` is the fastest way to
749
create a puzzle.
750
751
Or if only one solution is needed it can be obtained with
752
one call to ``next()``, while the existence of a solution
753
can be tested by catching the ``StopIteration`` exception
754
with a ``try``. Calling this particular method returns
755
solutions as lists, in row-major order. It is up to you
756
to work with this list for your own purposes. If you want
757
fancier formatting tools, use the
758
:func:`~sage.games.sudoku.Sudoku.solve` method, which
759
returns a generator that creates
760
:class:`sage.games.sudoku.Sudoku` objects.
761
762
EXAMPLES:
763
764
A `9\times 9` known to have one solution. We get the one
765
solution and then check to see if there are more or not. ::
766
767
sage: e = Sudoku('4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......')
768
sage: print e.dlx().next()
769
[4, 1, 7, 3, 6, 9, 8, 2, 5, 6, 3, 2, 1, 5, 8, 9, 4, 7, 9, 5, 8, 7, 2, 4, 3, 1, 6, 8, 2, 5, 4, 3, 7, 1, 6, 9, 7, 9, 1, 5, 8, 6, 4, 3, 2, 3, 4, 6, 9, 1, 2, 7, 5, 8, 2, 8, 9, 6, 4, 3, 5, 7, 1, 5, 7, 3, 2, 9, 1, 6, 8, 4, 1, 6, 4, 8, 7, 5, 2, 9, 3]
770
sage: len(list(e.dlx()))
771
1
772
773
A `9\times 9` puzzle with multiple solutions.
774
Once with actual solutions, once just to count. ::
775
776
sage: h = Sudoku('8..6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......')
777
sage: len(list(h.dlx()))
778
5
779
sage: len(list(h.dlx(count_only=True)))
780
5
781
782
A larger puzzle, with multiple solutions, but we just get one. ::
783
784
sage: j = Sudoku('....a..69.3....1d.2...8....e.4....b....5..c.......7.......g...f....1.e..2.b.8..3.......4.d.....6.........f..7.g..9.a..c...5.....8..f.....1..e.79.c....b.....2...6.....g.7......84....3.d..a.5....5...7..e...ca.....3.1.......b......f....4...d..e..g.92.6..8....')
785
sage: print j.dlx().next()
786
[5, 15, 16, 14, 10, 13, 7, 6, 9, 2, 3, 4, 11, 8, 12, 1, 13, 3, 2, 12, 11, 16, 8, 15, 1, 6, 7, 14, 10, 4, 9, 5, 1, 10, 11, 6, 9, 4, 3, 5, 15, 8, 12, 13, 16, 7, 14, 2, 9, 8, 7, 4, 12, 2, 1, 14, 10, 5, 16, 11, 6, 3, 15, 13, 12, 16, 4, 1, 13, 14, 9, 10, 2, 7, 11, 6, 8, 15, 5, 3, 3, 14, 5, 7, 16, 11, 15, 4, 12, 13, 8, 9, 1, 2, 10, 6, 2, 6, 13, 11, 1, 8, 5, 3, 4, 15, 14, 10, 7, 9, 16, 12, 15, 9, 8, 10, 2, 6, 12, 7, 3, 16, 5, 1, 4, 14, 13, 11, 8, 11, 3, 15, 5, 10, 4, 2, 13, 1, 6, 12, 14, 16, 7, 9, 16, 12, 14, 13, 7, 15, 11, 1, 8, 9, 4, 5, 2, 6, 3, 10, 6, 2, 10, 5, 14, 12, 16, 9, 7, 11, 15, 3, 13, 1, 4, 8, 4, 7, 1, 9, 8, 3, 6, 13, 16, 14, 10, 2, 5, 12, 11, 15, 11, 5, 9, 8, 6, 7, 13, 16, 14, 3, 1, 15, 12, 10, 2, 4, 7, 13, 15, 3, 4, 1, 10, 8, 5, 12, 2, 16, 9, 11, 6, 14, 10, 1, 6, 2, 15, 5, 14, 12, 11, 4, 9, 7, 3, 13, 8, 16, 14, 4, 12, 16, 3, 9, 2, 11, 6, 10, 13, 8, 15, 5, 1, 7]
787
788
The puzzle ``h`` from above, but purposely made unsolvable with addition in second entry. ::
789
790
sage: hbad = Sudoku('82.6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......')
791
sage: len(list(hbad.dlx()))
792
0
793
sage: hbad.dlx().next()
794
Traceback (most recent call last):
795
...
796
StopIteration
797
798
A stupidly small puzzle to test the lower limits of arbitrary sized input. ::
799
800
sage: s = Sudoku('.')
801
sage: print s.solve(algorithm='dlx').next()
802
+-+
803
|1|
804
+-+
805
806
ALGORITHM:
807
808
The ``DLXCPP`` solver finds solutions to the exact-cover
809
problem with a "Dancing Links" backtracking algorithm.
810
Given a `0-1` matrix, the solver finds a subset of the
811
rows that sums to the all `1`'s vector. The columns
812
correspond to conditions, or constraints, that must be
813
met by a solution, while the rows correspond to some
814
collection of choices, or decisions. A `1` in a row
815
and column indicates that the choice corresponding to
816
the row meets the condition corresponding to the column.
817
818
So here, we code the notion of a Sudoku puzzle, and the
819
hints already present, into such a `0-1` matrix. Then the
820
:class:`sage.combinat.matrices.dlxcpp.DLXCPP` solver makes
821
the choices for the blank entries.
822
"""
823
from sage.combinat.matrices.dlxcpp import DLXCPP
824
825
n = self.n
826
nsquare = n*n
827
nfour = nsquare*nsquare
828
829
# Boxes of the grid are numbered in row-major order
830
# ``rcbox`` simply maps a row-column index pair to the box number it lives in
831
rcbox = [ [i//n + n*(j//n) for i in range(nsquare)] for j in range(nsquare)]
832
833
# Every entry in a Sudoku puzzle satisfies four constraints
834
# Every location has a single entry, and each row, column and box has each symbol once
835
# These arrays can be thought of as assigning ID numbers to these constraints,
836
# and correspond to column numbers of the `0-1` matrix describing the exact cover
837
rows = [[i+j for i in range(nsquare)] for j in range(0, nfour, nsquare)]
838
cols = [[i+j for i in range(nsquare)] for j in range(nfour, 2*nfour, nsquare)]
839
boxes = [[i+j for i in range(nsquare)] for j in range(2*nfour, 3*nfour, nsquare)]
840
rowcol = [[i+j for i in range(nsquare)] for j in range(3*nfour, 4*nfour, nsquare)]
841
842
def make_row(row, col, entry):
843
r"""
844
Constructs a row of the `0-1` matrix describing
845
the exact cover constraints for a Sudoku puzzle.
846
847
If a (zero-based) ``entry`` is placed in location
848
``(row, col)`` of a Sudoku puzzle, then exactly four
849
constraints are satisfied: the location has this entry,
850
and the entry occurs in the row, column and box.
851
This method looks up the constraint IDs for each of
852
these four constraints, and returns a list of these four IDs.
853
854
TEST::
855
856
sage: h = Sudoku('8..6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......')
857
sage: len(list(h.solve(algorithm='dlx'))) # indirect doctest
858
5
859
"""
860
box = rcbox[row][col]
861
return [rows[row][entry], cols[col][entry], boxes[box][entry], rowcol[row][col]]
862
863
# Construct the sparse `0-1` matrix for the exact cover formulation as the ``ones`` array
864
# ``rowinfo`` remembers the location and entry that led to the row being added to the matrix
865
rowinfo = []
866
ones = []
867
gen = (entry for entry in self.puzzle)
868
for row in range(nsquare):
869
for col in range(nsquare):
870
puzz = gen.next()
871
# All (zero-based) entries are possible, or only one is possible
872
entries = ([puzz-1] if puzz else range(nsquare))
873
for entry in entries:
874
ones.append(make_row(row, col, entry))
875
rowinfo.append((row, col, entry))
876
877
# ``DLXCPP`` will solve the exact cover problem for the ``ones`` matrix
878
# ``cover`` will contain a subset of the row indices so that the sum of the rows is the all `1`'s vector
879
# These rows will represent the original hints, plus a single entry in every other location,
880
# consistent with the requirements imposed on a solution to a Sudoku puzzle
881
for cover in DLXCPP(ones):
882
if not(count_only):
883
solution = [0]*nfour
884
for r in cover:
885
row, col, entry = rowinfo[r]
886
solution[row*nsquare+col] = entry+1
887
yield solution
888
else:
889
yield None
890
891
892
893
894
895
896
897