Search code examples
pythonfunctionbacktracking

How to use a variable in a function that returns None?


I have the following function, it is used to solve a sudoku grid. How can I change the code such that it returns the solved matrix so that I can use it for something else, instead of only printing it? The function basically uses recursion to try out all possible solutions for the sudoku grid and fills in a number if it belongs in a certain position. source: https://www.youtube.com/watch?v=G_UYXzGuqvM&t=455s

matrix = np.array([[9,0,7,   1,0,0,   0,0,0],
                   [0,0,0,   0,0,0,   0,0,0],
                   [5,0,0,   3,0,0,   0,6,9],

                   [0,0,1,   6,5,0,   8,0,0],
                   [0,3,0,   0,8,0,   0,4,0],
                   [0,0,6,   0,3,9,   1,0,0],

                   [4,2,0,   0,0,6,   0,0,8],
                   [0,0,0,   0,0,0,   0,0,0],
                   [0,0,0,   0,0,2,   5,0,7]])

def grid(i,j): # function which splits the matrix up into 9 grids
    if i < 3 and j < 3:
        return matrix[0:3,0:3]
    elif  i < 3 and 3 <= j < 6 :
        return matrix[0:3,3:6]
    elif  i < 3 and 6 <= j < 9 :
        return matrix[0:3,6:9]
    elif  3 <= i < 6 and j < 3 :
        return matrix[3:6,0:3]
    elif  3 <= i < 6 and 3 <= j < 6 :
        return matrix[3:6,3:6]
    elif  3 <= i < 6 and 6 <= j < 9:
        return matrix[3:6,6:9]
    elif  6 <= i < 9 and j < 3 :
        return matrix[6:9,0:3]
    elif  6 <= i < 9 and 3 <= j < 6 :
        return matrix[6:9,3:6]
    elif  6 <= i < 9 and 6 <= j < 9 :
        return matrix[6:9,6:9] #

def possible(i,j,n): # function which tells us if a number is possible in a certain position
    if all(matrix[i][m] != n and matrix[m][j] != n for m in range(9)) and n not in grid(i,j):
        return True
    else:
        return False

def solve(): # function which solves the puzzle and fills in correct digits
    global matrix
    for i in range(9):
        for j in range(9):
            if matrix[i][j] == 0:
                for n in range(1,10):
                    if possible(i,j,n):
                        matrix[i][j] = n
                        solve()
                        matrix[i][j] = 0
                return
    print(matrix)


solve()

I have tried to use return matrix but this just returns the original matrix


Solution

  • The problem with your code is that you are working on a global matrix. Somewhere deep down the recursive calls you find the solution (and print it) but when returning up the stack you reset all fields back to 0. (See chepner's comment.)

    Given that you are coding in a "procedural style", why not use a second global variable (solution say) and assign a deep copy.

    from copy import deepcopy
    
    ...
    
    
    solution = deepcopy(matrix)
    

    Of course you could also restructure the code in a more functional style.