def answer_solve_sudoku(__grid):
res = check_sudoku(__grid)
if res is None or res is False:
return res
grid = copy.deepcopy(__grid)
# find the first 0 element and change it to each of 1..9,
# recursively calling this function on the result
for row in xrange(9):
for col in xrange(9):
if grid[row][col] == 0:
for n in xrange(1, 10):
grid[row][col] = n
new = answer_solve_sudoku(grid)
if new is not False:
return new
# backtrack
return False
# if we get here, we found no zeros and so we're finished
return grid
Here is the code, and check_sudoku(grid) can return if a grid is a valid sudoku or not.
I just can’t understand the recursion part, I tried to write down the process on the paper, but it failed everytime, how is backtraking working? and what is new? if the answer_solve_sudoku(grid) is valid?
I know it sets every 0 to 1..9, and checks if it’s a valid grid or not, but I just can’t draw the whole process on the paper. And can’t really understand how the backtrack is working.
btw, is there any advice of understanding recursion code?
Best Regards,
Sheng Yun
EDIT
I read the code again and again, and now I have some understanding, but I’m just not that sure about this, it will be kind if anyone gives me some comments.
1, return new will only be called when the solver found the solution, and this will be called right after return grid
2, when will
# backtrack
return False
be called? if the next solution isn’t right, check_sudoku(__grid) will return False, and if the next solution is right, it will call another answer_solve_sudoku(grid) till it gets the right solution, and when it gets the right solution, it will return grid and then return new. So when is:
# backtrack
return False
called?
Rather than writing this out on paper, I have a better recommendation. Format the code to show you a visual representation of what the logic is doing. Here is a way to do that:
What I did was create a little printer function that will print a number and indent the message by that many spaces. Then in your
answer_solve_sudoku, I gave it a default counter value of 0, and always pass in counter+1 to each recursive call. That way as the depth grows, so will the number. And I put printer functions along to way to visually illustrate what is happening.What you will see is something like this:
Yes, when a call to
answer_solve_sudokumakes its way through that whole loop without failing and reaches the bottom, it has succeeded and returns the grid. The caller will then get that grid as a result tonew = answer_solve_sudoku(grid)and return that. The grid will make its way back up each returning call on the stack.Because you are creating a copy of the grid in each recursion, unless that step finds the solution, the changes it made to that grid will be discarded, since once we return back up one step we will be back to our previous grid state. It tries to go as far as it can with that solution until it runs past the value of 9.