forked from lukehammer/suduku_slover
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsudokuSlover.py
389 lines (316 loc) · 12 KB
/
sudokuSlover.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
__author__ = 'student'
import math
#viewed by Cissie Scurlock
def enterpuzzle(puzzle):
while True:
# puzzle = raw_input('please enter your 81 digit puzzle use "." for blank spots :\n')
# Validate that user input is len = 81
if not len(puzzle) == 81:
print("please enter a value that is equal to 81 charactors long. Please try again")
continue
#Validate that user input only has numbers or .
valid = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "."]
for char in puzzle:
if not char in valid:
print(char + " is not a valid value please reenter puzzle without using " + char)
break
def display(puzzle):
display = ''
ii = 0
for char in puzzle:
# format first line
if ii % 81 == 0:
display = "+---+---+---+\n|" + char
# format rows
elif ii % 27 == 0:
display = display + "|\n+---+---+---+\n|" + char
# format last column
elif ii % 9 == 0:
display = display + "|\n|" + char
# format columns
elif ii % 3 == 0:
display = display + "|" + char
# insert nonformated data
else:
display = display + char
ii += 1
display = display + "|\n+---+---+---+"
print(display)
def find_row(numbervalue):
row = numbervalue / 9
row = math.floor(row)
row = int(row)
return row
# given any position in the puzzle this will return the row
def find_column(numbervalue):
column = numbervalue % 9
column = int(column)
return column
return
# given any position in the puzzle this will return the column
def find_box(numbervalue):
# finds the box that a given cell belongs to e.g. start with upper left 0
row = find_row(numbervalue)
row = row / 3
row = math.floor(row)
column = find_column(numbervalue)
column = column / 3
column = math.floor(column)
box_number = column + row * 3
box_number = int(box_number)
return box_number
# given any position in the puzzle this will return the boxNumber
def cell_current_properties():
return
def check_for_available_values(cell_index):
return
def get_all_indexs_for_row(row):
indexs = []
for x in range(0, 9):
next_index = x + 9 * row
indexs.append(next_index)
return indexs
def get_all_indexs_for_column(column):
"""
given any index in the puzzle this returns a list of indexs in that column
:param column: column number
:return: indexs[]
"""
indexs = []
for x in range(0, 9):
next_index = x * 9 + column
indexs.append(next_index)
return indexs
def get_all_indexs_for_box(box):
"""
given any index in the puzzle this returns a list of indexs in that box
:param box: box number
:return: indexs[]
"""
row = box / 3
row = int(math.floor(row))
row = row * 27
column = box % 3
column = int(math.floor(column))
column = column * 3
indexs = []
for x in range(0, 3):
for y in range(0, 3):
next_index = x * 9 + y + column + row
indexs.append(next_index)
return indexs
def get_all_indexs_related_cell(index):
related_cells = []
box = find_box(index)
box = get_all_indexs_for_box(box)
related_cells.extend(box)
column = find_column(index)
column = get_all_indexs_for_column(column)
related_cells.extend(column)
row = find_row(index)
row = get_all_indexs_for_row(row)
related_cells.extend(row)
related_cells = set(related_cells)
related_cells = list(related_cells)
return related_cells
def get_possable_locations_for_number(unsloved_list, puzzle, value):
possable_locations = []
# loop though each unsloved value
for orgain_cell in unsloved_list:
possable = can_cell_be_value(puzzle, value, orgain_cell)
if possable:
possable_locations.append(orgain_cell)
return possable_locations
# active_column = find_column(cell)
#active_box = find_box(cell)
return
def get_unsloved_cells(puzzle):
unsloved = []
ii = 0
for char in puzzle:
if char == ".":
unsloved.append(ii)
ii += 1
# returns unsloved index
return unsloved
def get_number_values(cell_index_list, puzzle):
# given a list of cell indexs returns a list of the values contained
values = []
for index in cell_index_list:
if not puzzle[index] == ".":
value = puzzle[index]
values.append(value)
return values
def can_cell_be_value(puzzle, value, cell):
related_cells = get_all_indexs_related_cell(cell)
for related_cell in related_cells:
cell_puzzle_value = puzzle[related_cell]
if cell_puzzle_value == '.':
continue
if value == int(cell_puzzle_value):
return False
return True
def search_for_only_in_row(possable_locations):
for ii in range(9):
row = get_all_indexs_for_row(ii)
valid_index_for_row = set(possable_locations) & set(row)
if len(valid_index_for_row) == 1:
print ("you found a value for index " + str(valid_index_for_row))
print (valid_index_for_row)
def search_for_only_in_box(possable_locations):
for ii in range(9):
column = get_all_indexs_for_column(ii)
valid_index_for_box = set(possable_locations) & set(box)
if len(valid_index_for_box) == 1:
print ("you found a value for index " + str(valid_index_for_box))
print (valid_index_for_box)
def search_for_only_in_column(possable_locations):
for ii in range(9):
column = get_all_indexs_for_column(ii)
valid_index_for_column = set(possable_locations) & set(column)
if len(valid_index_for_column) == 1:
print ("you found a value for index " + str(valid_index_for_column))
print (valid_index_for_column)
def search_for_only_in_area(possable_locations):
area = []
for ii in range(9):
row = get_all_indexs_for_row(ii)
column = get_all_indexs_for_column(ii)
box = get_all_indexs_for_box(ii)
area.append(row)
area.append(column)
area.append(box)
for list in area:
valid_values_for_area = set(possable_locations) & set(list)
if len(valid_values_for_area) == 1:
valid_values_for_area = valid_values_for_area.pop()
row = find_row(valid_values_for_area) + 1
column = find_column(valid_values_for_area) + 1
print ("\tYou found a value for row " + str(row) + " & column " + str(column) + ' in area ' + str(list))
return valid_values_for_area
elif len(valid_values_for_area) > 1:
print (" can not slove for there are " + str(len(valid_values_for_area)) + ' in area these values' + str(list) + " in this round")
def uniq(input):
## used to remove non unique items
output = []
for x in input:
if x not in output:
output.append(x)
return output
def change_sloved_locations(puzzle,sloved_value,sloved_locations):
if sloved_locations == None:
return puzzle
puzzle = list(puzzle)
puzzle[sloved_locations] = str(sloved_value)
puzzle = ''.join(puzzle)
return puzzle
def single_pass(puzzle):
enterpuzzle(puzzle)
for ii in range(1,10):
old_puzzle = puzzle
value = ii
unsloved = get_unsloved_cells(puzzle)
possable_locations = get_possable_locations_for_number(unsloved, puzzle, value)
print ("checking for value " + str(ii))
solved_locations = search_for_only_in_area(possable_locations)
puzzle = change_sloved_locations(puzzle,value,solved_locations)
if not old_puzzle == puzzle:
display(puzzle)
return puzzle
def simple_slove(puzzle):
old_puzzle =''
while not puzzle == old_puzzle:
old_puzzle = puzzle
puzzle = single_pass(puzzle)
return puzzle
def find_possiable_cells_per_value(puzzle):
unsloved_list = get_unsloved_cells(puzzle)
for ii in range(1,10):
possable_for_value = get_possable_locations_for_number(unsloved_list,puzzle,ii)
possable_list.update({ii:possable_for_value})
return possable_list
def find_nunber_of_possiable_values_per_cell(puzzle):
# given any puzzle show the cell indicator then the possiable values for the empty cells
# input puzzle as a text string
# output is dictanary that has cells at the key values and connect lists.
possiable_cell_per_value = find_possiable_cells_per_value(puzzle)
possiable_value_per_cell = {}
for value in possiable_cell_per_value.keys():
possiable_for_single_value = possiable_cell_per_value.get(value)
print value, possiable_for_single_value
unsloved_idexes = []
for ii in possiable_for_single_value:
print value, ii
unsloved_idexes.append(ii)
possiable_value_per_cell.update({value:unsloved_idexes})
print possiable_value_per_cell
#print possiable_value_per_cell
for value in possiable_value_per_cell:
t = 1
#print str(value) + " : " + str(possiable_value_per_cell.get(value))
def find_nunber_of_possiable_values_per_cell(puzzle):
# given any puzzle show the cell indicator then the possiable values for the empty cells
# input puzzle as a text string
# output is dictanary that has cells at the key values and connect lists.
possiable_cell_per_value = find_possiable_cells_per_value(puzzle)
possiable_value_per_cell = {}
for value in possiable_cell_per_value.keys():
possiable_for_single_value = possiable_cell_per_value.get(value)
print value, possiable_for_single_value
unsloved_idexes = []
for ii in possiable_for_single_value:
print value, ii
unsloved_idexes.append(ii)
possiable_value_per_cell.update({value:unsloved_idexes})
print possiable_value_per_cell
#print possiable_value_per_cell
for value in possiable_value_per_cell:
t = 1
#print str(value) + " : " + str(possiable_value_per_cell.get(value))
def main(puzzle):
puzzle = simple_slove(puzzle)
if "." in puzzle:
print ("Can not be full sloved by slover yet.")
display(puzzle)
print ("Can not be full sloved by slover yet.")
else:
display(puzzle)
print ("Done")
return puzzle
puzzle = '..9.43..........3.41..7.............8..5...6..4...6..2.......1...4.98..67..6..52.'
puzzle = '.....5....2...4.1..3..8..2......84..8..6......9..1.7.5..6......95...3.6...3.....1'
puzzle = '.....5....2..64.1..3..8..2......84..8..6......9..1.7.5..6......95...3.6...3.....1'
puzzle = '.....5....2...4.1..3..8..2......84..8..6......9..1.7.5..6......95...3.6...3.....1'
puzzle = '..........37.9..2..2...84.76...4.....8...71....3.6..5.278..69............9.4...3.'
puzzle = '..........37.9..2..2...84.76...4.....8...71....3.6..5.278..69............9.4...3.'
#puzzle = '....4....1..9..64..3....8....7.........1.859.......3...52..1....1.7.3...39..5...4'
puzzle = main(puzzle)
for value in range(1,10):
count = 0
for index in puzzle:
if str(value) == index:
count += 1
count = 9 - count
print ("there are %s left to slove for number %s" %(count, value))
unsloved_list = get_unsloved_cells(puzzle)
possable_list = {}
for ii in range(1,10):
possable_for_value = get_possable_locations_for_number(unsloved_list,puzzle,ii)
possable_list.update({ii:possable_for_value})
for ii in range(1,10):
print ii, ':', possable_list.get(ii)
print find_possiable_cells_per_value(puzzle)
possable_for_value = find_nunber_of_possiable_values_per_cell(puzzle)
possable_for_value = {}
for ii in possable_for_value.keys():
print ii
#print (can_cell_be_value(puzzle,2,0))
#print (can_cell_be_value(puzzle,9,0))
#display(puzzle)
#give me a puzzle
#for this puzzle give me all that place that can be 1
#look at the first place that can be 1
#can any other value in this row be 1?
#can any other value in this colomn be 1?
#can any other value in this box ?
#if so change len[index] to 1