-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSudokuSolver.py
177 lines (134 loc) · 5.82 KB
/
SudokuSolver.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
from utility import getBlock, getBox, getNumber, getVarNumber
from display import displaySol
import displayGUI
import sys, os
import subprocess
file = open("SudokuSolution.cnf", mode='w')
puzzle = [
[8,0,0,0,0,3,0,7,0],
[0,0,0,6,0,0,0,9,0],
[0,0,0,0,0,0,2,0,0],
[0,5,0,0,0,0,0,0,0],
[0,0,7,0,4,5,1,0,0],
[0,0,0,7,0,0,0,3,0],
[0,0,1,0,0,8,0,9,0],
[0,0,0,5,0,0,0,0,0],
[0,6,8,0,1,0,4,0,0]
]
print()
print("hackrush sudoku solver")
print(" SUDOKU\n")
for i in range(3):
for row in range(3):
for blk in range(3*i, 3*(i+1)):
for col in range(3):
if puzzle[blk][row*3 + col] == 0:
print('-', end = ' ')
else:
print(puzzle[blk][row*3 + col], end=' ')
if (blk + 1)%3 != 0:
print('| ', end = '')
print()
if (i + 1)%3 != 0:
print("------+-------+-------")
# puzzle = inputGUI()
def main():
global file
# navigating block wise
for block in range(9):
# checks each box
for box in range(9):
varNumber = getVarNumber(block, box, puzzle[block][box]) # gets the SAT variable associated with the number
# if a number already exists in the box then row, col, and block constraints are output
if (puzzle[block][box] != 0):
file.write("{0:d} 0\n".format(varNumber)) # and writes it (+ve signifying true)
# writes -ve constraints
getCols(varNumber)
getRows(varNumber)
getBlocks(varNumber)
# else writes all the SAT variables as +ve in one clause as at least one should be true
else:
# all the variables
for i in range(9):
var = 81*block + 9*box + i + 1
file.write("{0:d} ".format(var))
file.write("{0:d}\n".format(0))
for i in range(9):
var = 81*block + 9*box + i + 1
getCols(var)
getRows(var)
getBlocks(var)
file.close()
nullOut = open(os.devnull, "w")
subprocess.call(['minisat', 'SudokuSolution.cnf', 'SudokuSolution.sol'], stdout=nullOut)
solution = displaySol()
displayGUI.outputGUI(solution)
# gets the SAT variable numbers in the same column
def getCols(varNumber):
global file
# gets the block, box and number associated with the SAT varNumber
block = getBlock(varNumber)
box = getBox(varNumber)
number = getNumber(varNumber)
colIndex = box % 3 # only 3 columns in a block, so mod 3 to get the column index from box number
prevBlock = block - 3 # starts with the block 3-before the current block
nextBlock = block + 3 # starts with the block 3-after the current block
# writes the SAT vars in the same column of the prev blocks
while(prevBlock >= 0):
# checks for each box(=i)
for i in range(9):
# writes if in the same column and is blank
if(i%3 == colIndex and puzzle[prevBlock][i] == 0):
file.write("-{0:d} -{1:d} 0\n".format(varNumber,getVarNumber(prevBlock, i, number)))
prevBlock = prevBlock - 3 # decreases the block by 3
# writes the SAT vars in the same column of the next blocks
while(nextBlock <= 8):
# checks for each box
for i in range(9):
# writes if in the same column and is blank
if(i%3 == colIndex and puzzle[nextBlock][i] == 0):
file.write("-{0:d} -{1:d} 0\n".format(varNumber,getVarNumber(nextBlock, i, number)))
nextBlock = nextBlock + 3
# gets the SAT variable numbers in the same row
def getRows(varNumber):
# gets the block, box and number associated with the SAT varNumber
block = getBlock(varNumber)
box = getBox(varNumber)
number = getNumber(varNumber)
rowIndex = int(box / 3) # only 3 rows in a block, so divided by 3 to get the row index from box number
prevBlock = block # starts with the current block
nextBlock = block # starts with the current block
# writes the SAT vars in the same row of the prev blocks
while(prevBlock % 3 != 0):
prevBlock = prevBlock - 1
# checks for each box
for i in range(9):
# writes if in the same row and is blank
if(int(i/3) == rowIndex and puzzle[prevBlock][i] == 0):
# write(prevBlock, i, number)
file.write("-{0:d} -{1:d} 0\n".format(varNumber,getVarNumber(prevBlock, i, number)))
# writes the SAT vars in the same row of the next blocks
while(nextBlock % 3 != 2):
nextBlock = nextBlock + 1
# checks for each box
for i in range(9):
# writes if in the same column and is blank
if(int(i/3) == rowIndex and puzzle[nextBlock][i] == 0):
# write(nextBlock, i, number)
file.write("-{0:d} -{1:d} 0\n".format(varNumber,getVarNumber(nextBlock, i, number)))
# gets the SAT variable numbers in the same block
def getBlocks(varNumber):
# gets the block, box and number associated with the SAT varNumber
block = getBlock(varNumber)
box = getBox(varNumber)
number = getNumber(varNumber)
# checks for each box
for i in range(9):
# writes if even if it is NOT blank as that leads to problems when the last box is already filled
# it doesn't generate the variables for the ones that are already input, and that may lead to missing
# cnf clauses(the code that worked before this was just luck I guess)
if(i != box):
# write(block, i,number)
file.write("-{0:d} -{1:d} 0\n".format(varNumber,getVarNumber(block, i, number)))
if __name__ == '__main__':
main()