Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
zmx0142857
GitHub Repository: zmx0142857/mini-games
Path: blob/master/py/sudoku/sudoku.py
363 views
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
4
stack = []
5
rows = [0 for _ in range(9)]
6
cols = [0 for _ in range(9)]
7
grids = [0 for _ in range(9)]
8
tries = 0
9
solutions = 0
10
11
def set_flag(i, j, n):
12
global rows
13
global cols
14
global grids
15
mask = 1 << n
16
rows[i] ^= mask
17
cols[j] ^= mask
18
grids[i//3*3+j//3] ^= mask
19
20
def test_flag(i, j, n):
21
global rows
22
global cols
23
global grids
24
global tries
25
tries += 1
26
mask = 1 << n
27
conflict = (rows[i] & mask) or (cols[j] & mask) or (grids[i//3*3+j//3] & mask)
28
return not conflict
29
30
'''
31
def test(sudoku, i, j, n):
32
global tries
33
tries += 1
34
for k in range(9):
35
if sudoku[i][k] == n or sudoku[k][j] == n:
36
return False
37
i -= i % 3
38
j -= j % 3
39
for k in range(i, i+3):
40
for l in range(j, j+3):
41
if sudoku[k][l] == n:
42
return False
43
return True
44
'''
45
46
def recur(sudoku, d):
47
global stack
48
global solutions
49
if d == len(stack):
50
log(sudoku)
51
solutions += 1
52
else:
53
i = stack[d][0]
54
j = stack[d][1]
55
for n in range(9, 0, -1):
56
if test_flag(i, j, n):
57
sudoku[i][j] = n
58
set_flag(i, j, n)
59
recur(sudoku, d+1)
60
sudoku[i][j] = 0
61
set_flag(i, j, n)
62
63
def solve(sudoku):
64
global stack
65
global tries
66
for i in range(9):
67
for j in range(9):
68
n = sudoku[i][j]
69
if n == 0:
70
stack.append((i, j))
71
else:
72
set_flag(i, j, n)
73
print('given numbers: %d\n' % (81-len(stack)))
74
recur(sudoku, 0)
75
print('found %d solution(s)' % solutions)
76
print('total tries: %d' % tries)
77
78
def check(sudoku):
79
if len(sudoku) != 9:
80
raise ValueError('a sudoku must be 9 x 9')
81
for line in sudoku:
82
if len(line) != 9:
83
raise ValueError('a sudoku must be 9 x 9')
84
for n in line:
85
if not isinstance(n, int):
86
raise TypeError('sudoku can only contain integers')
87
88
def log(sudoku):
89
buf = []
90
for i in range(9):
91
for j in range(9):
92
buf.append(' ' if sudoku[i][j] == 0 else str(sudoku[i][j]))
93
buf.append('|' if j == 2 or j == 5 else ' ')
94
buf.append('\n-----+-----+-----\n' if i == 2 or i == 5 else '\n')
95
print(''.join(buf))
96
97
def readfile(filename):
98
with open(filename, 'r') as f:
99
return [[int(n) for n in line.split()] for line in f.readlines()]
100
101
def read():
102
return [[int(n) for n in input().split()] for line in range(9)]
103
104
if __name__ == '__main__':
105
sudoku = [
106
[2, 0, 0, 4, 7, 0, 8, 0, 0],
107
[0, 0, 0, 0, 6, 8, 0, 0, 0],
108
[0, 0, 0, 0, 0, 5, 6, 0, 7],
109
[8, 0, 0, 0, 0, 0, 7, 3, 0],
110
[1, 9, 0, 0, 4, 0, 0, 8, 2],
111
[0, 2, 5, 0, 0, 0, 0, 0, 6],
112
[5, 0, 9, 3, 0, 0, 0, 0, 0],
113
[0, 0, 0, 8, 9, 0, 0, 0, 0],
114
[0, 0, 3, 0, 1, 7, 0, 0, 4]
115
]
116
sudoku = read()
117
check(sudoku)
118
log(sudoku)
119
solve(sudoku)
120
121