-
Notifications
You must be signed in to change notification settings - Fork 0
/
board.py
143 lines (113 loc) · 4.69 KB
/
board.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
import cell
import block
import pool
import random
from datetime import datetime
class Board:
def __init__(self):
random.seed(datetime.now())
self.solution_pool = pool.Pool()
self.all_cells = []
self.row_blocks = []
self.column_blocks = []
self.square_blocks = []
for i in range(9):
self.row_blocks.append(block.Block("row"))
self.column_blocks.append(block.Block("column"))
self.square_blocks.append(block.Block("square"))
for y in range(9):
row = []
for x in range(9):
# identify row, column and square blocks containing given cell
row_block = self.row_blocks[y]
column_block = self.column_blocks[x]
square_block = self.square_blocks[(y // 3) * 3 + (x // 3)]
# create new cell and save pointers to the row, column and square block containing it
c = cell.Cell(x, y, row_block, column_block, square_block, self.solution_pool)
# save cell in row, column and square block containing it
row.append(c)
row_block.add_cell(c)
column_block.add_cell(c)
square_block.add_cell(c)
self.all_cells.append(row)
self.amount_of_resets = 0
self.amount_of_guesses = 0
def get_cell(self, x, y):
return self.all_cells[y][x]
def get_amount_of_solved_cells(self):
amount = 0
for row in self.all_cells:
for c in row:
if c.is_solved:
amount += 1
return amount
def is_solved(self):
return self.get_amount_of_solved_cells() == 81
def add_solution(self, cell_to_be_solved, number, type_of_solution):
self.solution_pool.add_triplet((cell_to_be_solved, number, type_of_solution))
def add_solutions(self, triplets_as_string):
triplets = triplets_as_string.split(", ")
for triplet in triplets:
entries = triplet.split(" ")
try:
x = int(entries[0]) - 1
y = int(entries[1]) - 1
number = int(entries[2])
except ValueError:
print("Invalid input! If you are trying to set values on the board your input needs to be a (comma-separated) list of triplets 'x y number' where x, y and number must be numbers from 1 to 9.")
print("The following example would put an 8 in the top right corner and a 7 in the center of the board: 9 1 8, 5 5 7")
break
self.add_solution(self.get_cell(x, y), number, "INIT")
def solve_one_cell(self):
return self.solution_pool.execute_next_triple()
def guess_one_cell(self):
if self.is_solved():
print("Sudoku is already solved.")
else:
self.amount_of_guesses += 1
# collect all unsolved cells
unsolved_cells = []
for y in range(9):
for x in range(9):
c = self.all_cells[y][x]
if not c.is_solved:
unsolved_cells.append(c)
# pick a random unsolved cells
random_unsolved_cell = random.choice(unsolved_cells)
# pick a random possible number for this cell
random_possible_number = random.choice(random_unsolved_cell.possible_numbers)
# use these as guessed solution
self.solution_pool.add_triplet((random_unsolved_cell, random_possible_number, "GUESS"))
def solve_sudoku(self):
while True:
try:
while self.solve_one_cell():
pass
if self.is_solved():
break
self.guess_one_cell()
except Exception as e:
print(str(e.args[0]))
self.reset(False)
print("Solved sudoku with " + str(self.amount_of_resets) + " reset(s) and " + str(self.amount_of_guesses) + " guess(es) (in the final pass)")
def reset(self, clear_init_queue):
self.solution_pool.reset(clear_init_queue)
for i in range(9):
self.row_blocks[i].reset()
self.column_blocks[i].reset()
self.square_blocks[i].reset()
for row in self.all_cells:
for c in row:
c.reset()
self.amount_of_guesses = 0
if clear_init_queue:
self.amount_of_resets = 0
else:
self.amount_of_resets += 1
def __repr__(self):
s = ""
for i in range(9):
if i % 3 == 0:
s += "\n"
s += str(self.row_blocks[i])
return s