-
Notifications
You must be signed in to change notification settings - Fork 0
/
SudokuCreator.py
141 lines (121 loc) · 4.45 KB
/
SudokuCreator.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
#%%
import numpy as np
import pprint
import sys
import numpy.ma as ma
sys.setrecursionlimit(29000)
from copy import deepcopy
#%%
matrix = [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,7,0,2],[0,0,3,0,0,0,6,0,0],
[0,0,0,5,0,0,0,0,0],[0,0,1,6,0,0,3,0,0],[0,5,6,4,0,0,0,0,0],
[0,0,0,0,1,0,0,9,0],[0,0,0,0,2,0,0,7,0],[0,0,0,0,3,0,0,0,4]]
grid = matrix
global base_grid
base_grid = deepcopy(grid)
global matrix_DoF
matrix_DoF = [[9 for _ in range(9)] for _ in range(9)]
global allowed_pos
allowed_pos = [i for i in range(9)]
global options
options = [(-1,-2),(-1,2),(-2,1),(-2,-1),(1,2),(1,-2),(2,1),(2,-1)] #x,y possibilities
def print_sudoku(board):
global base_grid
a_1 = "┃" + ("━━━━"*9)[:-1] + "┃"
a = "┃" + ("┅┅┅+"*9)[:-1] + "┃"
b = "┃" + (" + + ┋"*3)[:-1] + "┃"
#a = '\033[47m' + a + '\033[0m'
#b = '\033[47m' + b + '\033[0m'
print(a_1)
for i, row in enumerate(board):
print((("┃" + " {} {} {} ┋"*3)[:-1] + '┃').format(*[' ' if x==0 else '\033[92m' + str(x) + '\033[0m' if base_grid[i][j] == x else '\033[34m' + str(x) + '\033[0m' for j, x in enumerate(row)]))
if i % 3 == 2 and i !=8:
print(a)
elif i == 8:
print(a_1)
else:
print(b)
def normal_sudoku_rules_apply(y,x,n):
global grid
if grid[y][x] != 0: return False #there is a number
for i in range(9):
if grid[y][i] == n: #number in the colummn
return False
for i in range(9):
if grid[i][x] == n: #number in the row
return False
x0, y0 = (x//3)*3,(y//3)*3
for i in range(3):
for j in range(3):
if grid[y0+i][x0+j] == n: #number in the box
return False
return True
def knights_move_constraint(y,x,n):
global grid
global allowed_pos
global options
for op in options:
if x+op[0] in allowed_pos and y+op[1] in allowed_pos: #if it doesn't passes the grid dimensions
if grid[y+op[1]][x+op[0]] == n:
return False
return True
def possible(y,x,n):
normal = normal_sudoku_rules_apply(y,x,n)
knights = knights_move_constraint(y,x,n)
if normal and knights: #it is possible by both constraints
return True
else:
return False
def less_degrees_of_freedom():
global grid
global matrix_DoF
matrix_DoF = [[9 for _ in range(9)] for _ in range(9)]
grid_numpy = np.matrix(grid)
for x in range(9):
for y in range(9):
x0, y0 = (x//3)*3,(y//3)*3
box_numbers = []
row_numbers= []
columm_numbers = []
knight_numbers = []
for i in range(3):
for j in range(3):
if grid_numpy[y0+i, x0+j] !=0 : #number in the box
box_numbers.append(grid_numpy[y0+i, x0+j])
for op in options:
if x+op[0] in allowed_pos and y+op[1] in allowed_pos: #if it doesn't passes the grid dimensions
if grid_numpy[y+op[1], x+op[0]] != 0:
knight_numbers.append(grid_numpy[y+op[1], x+op[0]])
if grid_numpy[y, x] != 0 :
matrix_DoF[y][x] = 0
else: #there's a empty space
for i in range(9): row_numbers.append(grid_numpy[y,i])
for j in range(9): columm_numbers.append(grid_numpy[j,x])
numbers = np.unique(np.array(row_numbers + columm_numbers + box_numbers))
numbers = numbers[numbers != 0]
matrix_DoF[y][x] -= (len(numbers))
return matrix_DoF
def solve():
global grid
matrix_DoF = less_degrees_of_freedom()
numpy_DoF = np.array(matrix_DoF)
minvalpos = np.argmin(ma.masked_where(numpy_DoF==0, numpy_DoF))
minvalposy, minvalposx = minvalpos//9, minvalpos%9
# Get the indices of minimum element in numpy array
#That means the element with lest degrees of freedom
y, x = minvalposy, minvalposx
if grid[y][x] == 0: #blanck space
for n in range(1,10):
if possible(y,x,n):
grid[y][x] = n #if the number fits there, we try it!
solve() #and we try to solve it...
grid[y][x] = 0 #if we came back here it didn't work....
return
print_sudoku(grid)
input("More solutions?")
#%%
print_sudoku(base_grid)
trying = input("Wanna see the solution? y/n ")
if trying == 'y':
solve()
else: print("Fuck you, then!")
# %%