python version functional
This commit is contained in:
151
solver.py
Normal file
151
solver.py
Normal file
@@ -0,0 +1,151 @@
|
||||
from grid import *
|
||||
from copy import deepcopy
|
||||
|
||||
def solve(G):
|
||||
stack = [G]
|
||||
while len(stack) > 0:
|
||||
grid = stack.pop()
|
||||
ret = simplify(grid)
|
||||
if ret == 0:
|
||||
branch(grid, stack)
|
||||
print(G)
|
||||
printn("unsolvable!")
|
||||
|
||||
def simplify(G):
|
||||
sum = 1
|
||||
while sum > 0:
|
||||
sum = 0
|
||||
ret = check_rows(G)
|
||||
if ret < 0:
|
||||
return -1
|
||||
else:
|
||||
sum += ret
|
||||
|
||||
ret = check_cols(G)
|
||||
if ret < 0:
|
||||
return -1
|
||||
else:
|
||||
sum += ret
|
||||
|
||||
ret = check_squares(G)
|
||||
if ret < 0:
|
||||
return -1
|
||||
else:
|
||||
sum += ret
|
||||
|
||||
ret = reduce(G)
|
||||
if ret < 0:
|
||||
return -1
|
||||
else:
|
||||
sum += ret
|
||||
return 0
|
||||
|
||||
def branch(G, stack):
|
||||
min_cell = None
|
||||
min_cell_size = 10
|
||||
for cell in G.cells:
|
||||
if cell.is_set == False and len(cell.candidates) < min_cell_size:
|
||||
min_cell = cell
|
||||
min_cell_size = len(cell.candidates)
|
||||
candidates = min_cell.candidates
|
||||
for candidate in candidates:
|
||||
copy = deepcopy(G)
|
||||
copy.cells[min_cell.n].set(candidate)
|
||||
stack.append(copy)
|
||||
|
||||
def reduce(G):
|
||||
n_steps = 0
|
||||
while True:
|
||||
val = reduce_step(G)
|
||||
if val == 0:
|
||||
print(G)
|
||||
print("done")
|
||||
exit(0)
|
||||
elif val == 1:
|
||||
return n_steps
|
||||
n_steps += 1
|
||||
|
||||
def reduce_step(G):
|
||||
all_set = True
|
||||
nochange = True
|
||||
for cell in G.cells:
|
||||
l = len(cell.candidates)
|
||||
if not cell.is_set:
|
||||
if l == 1:
|
||||
cell.set(cell.candidates[0])
|
||||
nochange = False
|
||||
else:
|
||||
all_set = False
|
||||
if all_set:
|
||||
return 0
|
||||
elif nochange:
|
||||
return 1
|
||||
else:
|
||||
return 2
|
||||
|
||||
def check_rows(G):
|
||||
res = 0
|
||||
for row in G.rows:
|
||||
finds = [0]*9
|
||||
to_set = []
|
||||
for cell in row:
|
||||
cell = G.cells[cell]
|
||||
for candidate in cell.candidates:
|
||||
finds[candidate-1] += 1
|
||||
for i, find in enumerate(finds):
|
||||
if find == 1:
|
||||
to_set.append(i+1)
|
||||
elif find == 0:
|
||||
return -1
|
||||
for cell in row:
|
||||
cell = G.cells[cell]
|
||||
for i in to_set:
|
||||
if i in cell.candidates and not cell.is_set:
|
||||
cell.set(i)
|
||||
res += 1
|
||||
return res
|
||||
|
||||
def check_cols(G):
|
||||
res = 0
|
||||
for col in G.cols:
|
||||
finds = [0]*9
|
||||
to_set = []
|
||||
for cell in col:
|
||||
cell = G.cells[cell]
|
||||
for candidate in cell.candidates:
|
||||
finds[candidate-1] += 1
|
||||
for i, find in enumerate(finds):
|
||||
if find == 1:
|
||||
to_set.append(i+1)
|
||||
elif find == 0:
|
||||
return -1
|
||||
for cell in col:
|
||||
cell = G.cells[cell]
|
||||
for i in to_set:
|
||||
if i in cell.candidates and not cell.is_set:
|
||||
cell.set(i)
|
||||
res += 1
|
||||
return res
|
||||
|
||||
def check_squares(G):
|
||||
res = 0
|
||||
for square in G.squares:
|
||||
finds = [0]*9
|
||||
to_set = []
|
||||
for cell in square:
|
||||
cell = G.cells[cell]
|
||||
for candidate in cell.candidates:
|
||||
finds[candidate-1] += 1
|
||||
for i, find in enumerate(finds):
|
||||
if find == 1:
|
||||
to_set.append(i+1)
|
||||
elif find == 0:
|
||||
return -1
|
||||
for cell in square:
|
||||
cell = G.cells[cell]
|
||||
for i in to_set:
|
||||
if i in cell.candidates and not cell.is_set:
|
||||
cell.set(i)
|
||||
res += 1
|
||||
return res
|
||||
|
||||
Reference in New Issue
Block a user