-1
import sys
sys.setrecursionlimit(1500)  # the default recursion limit is 1000


def print_grid(arr):
    for i in range(9):
        for j in range(9):
            print(arr[i][j])
    print('\n')


def find_empty_location(arr, l):
    for i in range(9):
        for j in range(9):
            if (arr[i][j] == 0):
                l[0] = i
                l[1] = j
                return True

    return False


def row_check(arr, row, num):
    for x in range(9):
        if arr[row][x] == num:
            return True

    return False


def col_check(arr, col, num):
    for i in range(9):
        if arr[i][col] == num:
            return True

    return False


def used_in_box(arr, row, col, num):
    for i in range(3):
        for j in range(3):
            if (arr[i + row][j + col] == num):
                return True

    return False


def check_location_is_safe(arr, row, col, num):
    return not row_check(arr, row, num) and not col_check(arr, col, num) and not used_in_box(arr, row - row % 3, col - col % 3, num)


def solve_sudoku(arr):
    l = [0, 0]
    if (not find_empty_location(arr, l)):
        return True

    row = l[0]
    col = l[1]

    for num in range(1, 10):
        if check_location_is_safe(arr, row, col, num):
            arr[row][col] == num

        if solve_sudoku(arr):
            return True

        else:
            arr[row][col] = 0
            return False


if __name__ == "__main__":
    grid = [[0 for x in range(9)] for y in range(9)]

    grid = [[3, 0, 6, 5, 0, 8, 4, 0, 0],
            [5, 2, 0, 0, 0, 0, 0, 0, 0],
            [0, 8, 7, 0, 0, 0, 0, 3, 1],
            [0, 0, 3, 0, 1, 0, 0, 8, 0],
            [9, 0, 0, 8, 6, 3, 0, 0, 5],
            [0, 5, 0, 0, 9, 0, 6, 0, 0],
            [1, 3, 0, 0, 0, 0, 2, 5, 0],
            [0, 0, 0, 0, 0, 0, 0, 7, 4],
            [0, 0, 5, 2, 0, 6, 3, 0, 0]]
    if (solve_sudoku(grid)):
        print_grid(grid)

    else:
        print('NO SOLUTION EXISTS')
Andronicus
  • 25,419
  • 17
  • 47
  • 88

1 Answers1

0

Before looking at the code, you should already realise that in a correct solution, the recursion depth should never have to be greater than the number of empty cells in the sudoku grid. So if recursion goes deeper than that, it should ring the bell that you actually have a bug that makes your code recurse infinitely. Increasing the recursion limit is the wrong reaction.

Instead you should debug and see what is actually happening. What I tend to do in such cases is add a depth=0 parameter to the recursive function (with default value 0). Then make sure the recursive call passes the value depth+1. Add an if depth > 5: raise ValueError("stop") in the function to make sure it does not run that often. Finally add some print statements to inspect what your grid looks like, which row/col are selected, ...etc. You would soon detect something is going terribly wrong...

Now to the code: there are the following issues in your solve_sudoku function:

  • arr[row][col] == num is not an assignment, but a comparison. So you actually never change the grid.
  • Even with the above correction, you still keep recursing without changing the grid when check_location_is_safe returns False. So the following lines should have been indented more, so they belong to the if block above it:

    if solve_sudoku(arr):
         return True
    else:
         arr[row][col] = 0
         # return False <--- not here (cf. previous issue)
    

    NB: Since in the if case you exit the function, there is actually no real need to have arr[row][col] = 0 in an else. So it could well be:

    if solve_sudoku(arr):
         return True
    arr[row][col] = 0
    
  • return False should not be inside the for loop, because you still want to verify alternative "moves" in next iterations of the loop. return False should be executed after the loop has finished.

So taking those corrections together: the second half of solve_sudoku should look like this:

for num in range(1, 10):
    if check_location_is_safe(arr, row, col, num):
        arr[row][col] = num
        if solve_sudoku(arr):
            return True
        arr[row][col] = 0
return False
trincot
  • 317,000
  • 35
  • 244
  • 286