I am building a program that will solve sudoku puzzles. Here is the code:
def set_table(boxes_v, boxes_h, tiles_v, tiles_h):
""" boxes_v = boxes on vertical side of the whole table;
boxes_h = boxes on horixontal side of the whole table;
tiles_v = tiles on vertical line in each box;
tiles_h = tiles on horizontal line in each box.
"""
total_boxes = boxes_v * boxes_h
tiles_in_box = tiles_v * tiles_h
return [[{None : [False, 0]} for x in range(1, tiles_in_box + 1)] for a in range(total_boxes)]
def insert_numbers(table, numbers_and_positions):
""" table = sudoku table set up in "set_table";
numbers_and_postions = dictionary containing already given numbers and their positions in the table.
"""
noPos = numbers_and_positions
for number in noPos:
box = noPos[number][0]
tile = noPos[number][1]
table[box][tile] = {None : [True, number]}
return table
def test(table, index, number):
"Tests if number is suitable in a tile on vertical and horizontal lines"
box_index, tile_index = index
lines = {
0 : [(0,1,2), (0,3,6)],
1 : [(0,1,2), (1,4,7)],
2 : [(0,1,2), (2,5,8)],
3 : [(3,4,5), (0,3,6)],
4 : [(3,4,5), (1,4,7)],
5 : [(3,4,5), (2,5,8)],
6 : [(6,7,8), (0,3,6)],
7 : [(6,7,8), (1,4,7)],
8 : [(6,7,8), (2,5,8)]
}
box_line_h, box_line_v = lines[index[0]]
tile_line_h, tile_line_v = lines[index[1]]
################################### horizontal line tester
taken_numbers_h = []
for box_index in box_line_h:
index_counter = 0
for tile in table[box_index]:
if index_counter in tile_line_h:
taken_numbers_h.append(tile[None][1])
index_counter += 1
################################### vertical line tester
taken_numbers_v = []
for box_index in box_line_v:
index_counter = 0
for tile in table[box_index]:
if index_counter in tile_line_v:
taken_numbers_v.append(tile[None][1])
index_counter += 1
################################### box tester
taken_numbers_b = []
for tile in table[box_index]:
taken_numbers_b.append(tile[None][1])
###################################
taken_numbers = taken_numbers_h + taken_numbers_v + taken_numbers_b
if number in taken_numbers:
return True
elif number not in taken_numbers:
return False
def reset_key(dictionary, old_key, new_key, value):
"Resets a key of a dictionary to a different name"
dictionary[new_key] = dictionary[old_key]
del dictionary[old_key]
return dictionary
def solve(table):
""" Solves the sudoku puzzle
"""
box_index = 0
tile_index = 0
safe = True
def repeat():
tile[None][1] += 1
if tile[None][1] > 9:
tile[None][1] = 0
safe = False
tile_index -= 1
elif tile[None][1] <= 9:
if test(table, [box_index, tile_index], tile[None][1]) is True:
repeat()
elif test(table, [box_index, tile_index], tile[None][1]) is False:
tile_index += 1
safe = True
valid = False
while valid is not True:
box = table[box_index]
tile = box[tile_index]
if tile[None][0] is True:
if safe is True:
tile_index += 1
safe = True
elif safe is False:
tile_index -= 1
elif tile[None][0] is False:
repeat()
What I do in Python shell is:
>>>table = set_table(3,3,3,3)
>>>table = insert_numbers(table, {0 : [0,4]})
>>>solve(table)
What I expect to happen is the program changing the value of every dictionary on table[0] (box 1) to {None : [False, 1]}, {None : [False, 2]}, {None : [False, 3]} and so on until it reaches 9 at the last small box within the first big box of the whole grid because the code should cause an index error. This is because when it reaches the last small box in the first big box, an negative test result for violating the rules should come up for numbers 1-8 because they are obviously already in the box. I do not see this error, however, but this one instead:
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
solve(t)
File "C:\Users\cdobr\Desktop\Sudoku Solver.py", line 153, in solve
repeat()
File "C:\Users\cdobr\Desktop\Sudoku Solver.py", line 129, in repeat
if test(table, [box_index, tile_index], tile[None][1]) is True:
UnboundLocalError: local variable 'tile_index' referenced before assignment
What am I supposed to do to fix this? It is as if the function inside the function could not see the parent's variables.