forked from lilianweng/LeetcodePython
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsudoku_solver.py
100 lines (87 loc) · 2.67 KB
/
sudoku_solver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/env python
'''
Leetcode: Sudoku Solver
Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'.
You may assume that there will be only one unique solution.
'''
from __future__ import division
import sys
INVALID = 0
# fill in (x,y) with val@
def check_conflict(M, x, y, val):
# column
for i in range(9):
if M[i][y] != INVALID:
if M[i][y] == val:
return True
# row
for j in range(9):
if M[x][j] != INVALID:
if M[x][j] == val:
return True
# cubes
for i in range((x//3)*3, (x//3)*3+3):
for j in range((y//3)*3, (x//3)*3+3):
if M[i][j] != INVALID:
if M[i][j] == val:
return True
return False
def sudoku_fill_one(M, empty, rows, cols, cubes):
print len(empty), 'to fill'
# if no cell to fill
if len(empty) == 0: return True
i,j = empty[0]
# need to fill in
occupied = rows[i] | cols[j] | cubes[i//3,j//3]
cands = set(range(1,10)) - occupied
if not cands: return False
for c in cands:
#print 'Fill', c, 'in (%d,%d).' % (i,j)
M[i][j] = c
rows[i].add(c)
cols[j].add(c)
cubes[i//3,j//3].add(c)
if sudoku_fill_one(M, empty[1:], rows, cols, cubes):
return True
# trace back
M[i][j] = INVALID
rows[i].remove(c)
cols[j].remove(c)
cubes[i//3,j//3].remove(c)
def sudoku_solver(M):
# keep a set of elements for each row, column and cube
# rows[i]
rows = dict( \
(i, set([M[i][j] for j in range(9) if M[i][j] != INVALID])) \
for i in range(9))
# cols[j]
cols = dict( \
(j, set([M[i][j] for i in range(9) if M[i][j] != INVALID])) \
for j in range(9))
# cubes[i//3, j//3]
cubes = dict(\
((i,j), set([M[x][y] \
for x in range(i*3,i*3+3) \
for y in range(j*3,j*3+3) \
if M[x][y] != INVALID])\
) for i in range(3) for j in range(3))
# empty cells
empty = [(i,j) for i in range(9) for j in range(9) if M[i][j] == INVALID]
print rows
print cols
print cubes
print empty
sudoku_fill_one(M, empty, rows, cols, cubes)
print '\n'.join(map(str,M))
if __name__ == '__main__':
M = [[5,3,0,0,7,0,0,0,0],
[6,0,0,1,9,5,0,0,0],
[0,9,8,0,0,0,0,6,0],
[8,0,0,0,6,0,0,0,3],
[4,0,0,8,0,3,0,0,1],
[7,0,0,0,2,0,0,0,6],
[0,6,0,0,0,0,2,8,0],
[0,0,0,4,1,9,0,0,5],
[0,0,0,0,8,0,0,7,9]]
sudoku_solver(M)