-
Notifications
You must be signed in to change notification settings - Fork 0
/
cell.py
107 lines (83 loc) · 4.72 KB
/
cell.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
import board
class Cell:
def __init__(self, board_x, board_y, row_block, column_block, square_block, solution_pool):
self.board_x = board_x
self.board_y = board_y
self.row_block = row_block
self.column_block = column_block
self.square_block = square_block
self.possible_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] # order is irrelevant
self.is_solved = False
self.solution_pool = solution_pool
def reset(self):
self.possible_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
self.is_solved = False
def set_number_impossible(self, number):
if number in self.possible_numbers:
self.possible_numbers.remove(number)
# solution found because only one number left as possible for this cell
if len(self.possible_numbers) == 1:
self.solution_pool.add_triplet((self, self.possible_numbers[0], "POS_DED"))
# conflict: now no number is possible in this cell!
elif not self.possible_numbers:
# print("Conflict: for cell " + str(self) + " all 9 numbers are impossible!")
# return False
raise Exception("Conflict: for cell " + str(self) + " all 9 numbers are impossible!")
return True
def get_number(self):
if len(self.possible_numbers) == 1:
return self.possible_numbers[0]
else:
return -1
def set_number(self, number, comment):
#if self.is_solved:
#print("(" + comment + ": setting cell (" + str(self.board_x + 1) + "," + str(self.board_y + 1) + ") to number " + str(number) + ")")
#else:
if not self.is_solved:
print(comment + ": setting cell (" + str(self.board_x + 1) + "," + str(self.board_y + 1) + ") to number " + str(number))
# conflict: this cell is already set to a different number!
if self.is_solved and self.get_number() != number:
# print("Conflict: cell " + str(self) + " is assigned numbers " + str(self.get_number()) + " and " + str(number) + "!")
# return False
raise Exception("Conflict: cell " + str(self) + " is assigned numbers " + str(self.get_number()) + " and " + str(number) + "!")
self.is_solved = True
self.possible_numbers = [number]
# go through all 3 blocks containing this cell
for block in [self.row_block, self.column_block, self.square_block]:
for c in [x for x in block.cells if x != self]:
# set given number as impossible for all other cells in block
# if not c.set_number_impossible(number):
# return False
c.set_number_impossible(number)
# go through number-possible-cells map in block
for i in range(9):
# set current cell as only possible cell for given number in block
if i == number - 1:
block.number_possible_cells_map[i] = [self]
# set current cell as impossible for all other numbers in block
else:
if self in block.number_possible_cells_map[i]:
block.number_possible_cells_map[i].remove(self)
# if number can only go in one cell in block
if len(block.number_possible_cells_map[i]) == 1:
# then solve that cell
self.solution_pool.add_triplet((block.number_possible_cells_map[i][0], i + 1, "NEG_DED1(" + block.type_of_block + ")"))
# go through all 3 (second order) blocks containing current cell
for c_block in [c.row_block, c.column_block, c.square_block]:
# set current cell as impossible for number in current (second order) block
if c in c_block.number_possible_cells_map[number - 1]:
c_block.number_possible_cells_map[number - 1].remove(c)
# if number can only go in one cell in block
if len(c_block.number_possible_cells_map[number - 1]) == 1:
# then solve that cell using given number
self.solution_pool.add_triplet((c_block.number_possible_cells_map[number - 1][0], number, "NEG_DED2(" + block.type_of_block + ", " + c_block.type_of_block + ")"))
return True
def __repr__(self):
return "(" + str(self.board_x + 1) + "," + str(self.board_y + 1) + ")"
def pretty(self):
if not self.possible_numbers:
return "[X]"
elif len(self.possible_numbers) == 1:
return str(self.possible_numbers)
else:
return "[ ]"