-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOPBASolver.py
120 lines (94 loc) · 3.1 KB
/
OPBASolver.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
from config import Config as c, Temp as t
from BASolver2 import check, bASolverHandle as handleAdv
from time import sleep
import ujson
import copy
from functools import reduce
class InvaldSudoku(Exception):
pass
class NoNSolvable(Exception):
pass
t.possibls=[]
def OPSolverHandle(grid):
if any([not num<10 for row in grid for num in row]):
raise InvaldSudoku("Sudoku has value bigger than 9 ")
if len(grid)!=9 or len(grid[0])!=9:
raise InvaldSudoku("Sudoku is not Valid, it has to be 9x9")
return False
sols = []
solve(grid, sols)
grid = sols[0]
if any([not 0<num<10 for row in grid for num in row]):
raise NoNSolvable("Sudoku could not be solved")
return grid
def rowcoltoNum(row,col):
"""Converts 2D cooridinate to a 1D coordinate"""
return row*c.basesize**2+col
def getLen(elem):
"""This function is used to Sort the fileds by possibilities."""
leng=len(elem[0])
if leng!=0:
return leng
return 99
def numtoRowCol(num):
""""Convert number to row col"""
row=num//c.basesize**2
col=num % c.basesize**2
return (row,col)
def newPossiFinder(bo,i,j):
"""Gives the possible Numbers at a position on a sudoku grid. """
pickable = [True for _ in range(10)]
pickable[0] = False
for k in range(9):
pickable[bo[i][k]] = False
for k in range(9):
pickable[bo[k][j]] = False
r = j//3
c = i//3
for row in range(r*3,(r+1)*3):
for col in range(c*3,(c+1)*3):
pickable[bo[row][col]] = False
out=[]
for num, value in enumerate(pickable):
if value:
out.append(num)
return out
def advHandel(grid):
return handleAdv(grid)
def findPossi(bo):
""" Find all possibilities for all fields and add them to a list."""
possis = []
for row,rowVal in enumerate(bo):
for col,colVal in enumerate(rowVal):
localpossi=newPossiFinder(bo, col, row)
if bo[row][col]==0:
# Here ujson.loads(ujson.dumps()) is used because it is much faster than copy.deepcopy() to make a copy of a list.
possis.append(ujson.loads(ujson.dumps([localpossi,rowcoltoNum(row,col)])))
possis.sort(key=getLen)
t.possibls = possis
return possis
def solcountadv(bo):
"""Returns all Solutions"""
sols=[]
solveadv(bo,sols)
return sols
def solveadv(bo,sols=None):
solve(bo,sols)
def solve(bo,sols=None):
"""Solve Sudoku with Optimized Backtracking algorithm"""
posib=findPossi(bo)
print(posib)
for posi in posib:
ns=posi[0]
row,col = numtoRowCol(posi[1])
for n in ns:
if check(n, row, col, bo):
bo[row][col] = n
if solve(bo, sols):
return True
bo[row][col] = 0
return True
# if sum([0 if reduce(lambda x, y: x*y, boelem)!=0 else 1 for boelem in bo])!=0:
# reduce(lambda x, y: x*y, bo)
# Here ujson.loads(ujson.dumps()) is used because it is much faster than copy.deepcopy() to make a copy of a list.
sols.append(ujson.loads(ujson.dumps(bo)))