-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathsudoku_z3.py
executable file
·64 lines (45 loc) · 1.9 KB
/
sudoku_z3.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
#!/usr/bin/env python3
from sudoku import Sudoku
def z3_solving(sudoku):
""" Function solving the given sudoku puzzle using Z3 """
from z3 import Solver, Int, Or, Distinct, sat
#positions = cross("ABCDEFGHI", "123456789")
symbols = {pos: Int(pos) for pos in sudoku.positions}
# first we build a solver with the general constraints for sudoku puzzles:
s = Solver()
# assure that every cell holds a value of [1,9]
for symbol in symbols.values():
s.add(Or([symbol == i for i in range(1, 10)]))
# assure that every row covers every value:
for row in "ABCDEFGHI":
s.add(Distinct([symbols[row + col] for col in "123456789"]))
# assure that every column covers every value:
for col in "123456789":
s.add(Distinct([symbols[row + col] for row in "ABCDEFGHI"]))
# assure that every block covers every value:
for i in range(3):
for j in range(3):
s.add(Distinct([symbols["ABCDEFGHI"[m + i * 3] + "123456789"[n + j * 3]] for m in range(3) for n in range(3)]))
# now we put the assumptions of the given puzzle into the solver:
for pos, value in sudoku.grid.items():
if value in "123456789":
s.add(symbols[pos] == value)
if s.check() != sat:
raise Exception("unsolvable")
model = s.model()
values = {pos: model.evaluate(s).as_string() for pos, s in symbols.items()}
return Sudoku(values)
def main(puzzle):
print("[+] parsing puzzle:", puzzle)
s = Sudoku.parse(puzzle)
print("[+] start solving using Z3")
s_solved = z3_solving(s)
print("[+] solved:", s_solved.is_solved())
print(s_solved)
if __name__ == "__main__":
from sys import argv
if len(argv) != 2:
print("[!] we are using some test puzzle due to missing argument")
main("4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......")
else:
main(argv[1])