Search code examples
pythonnumpysudoku

Python Recursive Sudoku Solver Doesn't Return the Solution


I tried to optimize this code and my final code was as shown below

import numpy as np
sudoku = np.array([[0, 9, 0, 0, 5, 0, 6, 0, 8],
                   [0, 0, 0, 7, 1, 0, 3, 5, 0],
                   [2, 1, 0, 0, 0, 0, 7, 0, 4],
                   [0, 0, 1, 5, 0, 0, 0, 0, 6],
                   [6, 3, 0, 2, 0, 8, 0, 4, 5],
                   [7, 0, 0, 0, 0, 4, 9, 0, 0],
                   [9, 0, 3, 0, 0, 0, 0, 2, 1],
                   [0, 4, 8, 0, 2, 7, 0, 0, 0],
                   [5, 0, 6, 0, 8, 0, 0, 3, 0]])

#Checking if the number (n) can be placed there (row, col)
def check(sudoku, row, col, n):
    # Row check
    if np.sum(sudoku[row,:] == n) != 0: return False;
    # Col check
    if np.sum(sudoku[:,col] == n) != 0: return False;
    # Sqr check
    row0, col0 = (row//3)*3, (col//3)*3
    if np.sum(sudoku[row0:row0+3,col0:col0+3] == n) != 0: return False;
    return True

def solve_sudoku(sudoku):
    rows, cols = np.where(sudoku == 0)
    for row in rows:
        for col in cols:
            for num in range(1, 10):
                if check(sudoku, row, col, num):
                    sudoku[row, col] = num
                    solve_sudoku(sudoku)
                    sudoku[row, col] = 0
            return
    print(sudoku)
    return sudoku

solved = solve_sudoku(sudoku)

My problem is that even though the solution is successfully printed as shown below, the variable solved is just a NoneType and stores nothing.

[[3 9 7 4 5 2 6 1 8]
 [8 6 4 7 1 9 3 5 2]
 [2 1 5 8 3 6 7 9 4]
 [4 8 1 5 9 3 2 7 6]
 [6 3 9 2 7 8 1 4 5]
 [7 5 2 1 6 4 9 8 3]
 [9 7 3 6 4 5 8 2 1]
 [1 4 8 3 2 7 5 6 9]
 [5 2 6 9 8 1 4 3 7]]

TL;DR The function prints the solution but returns nothing. What should I do to store the printed solution?


Solution

  • After a few hours, I came up with this solution. solved stores the solution now.

    import numpy as np
    sudoku = np.array([[0, 9, 0, 0, 5, 0, 6, 0, 8],
                       [0, 0, 0, 7, 1, 0, 3, 5, 0],
                       [2, 1, 0, 0, 0, 0, 7, 0, 4],
                       [0, 0, 1, 5, 0, 0, 0, 0, 6],
                       [6, 3, 0, 2, 0, 8, 0, 4, 5],
                       [7, 0, 0, 0, 0, 4, 9, 0, 0],
                       [9, 0, 3, 0, 0, 0, 0, 2, 1],
                       [0, 4, 8, 0, 2, 7, 0, 0, 0],
                       [5, 0, 6, 0, 8, 0, 0, 3, 0]])
    solved = np.zeros_like(sudoku)
    
    def check(arg, row, col, n):
        if np.sum(arg[row,:] == n) != 0: return False;
        if np.sum(arg[:,col] == n) != 0: return False;
        row0, col0 = (row//3)*3, (col//3)*3
        if np.sum(arg[row0:row0+3,col0:col0+3] == n) != 0: return False;
        return True
    
    def solve_sudoku(arg):
        global solved
        rows, cols = np.where(arg == 0)
        for row in rows:
            for col in cols:
                for num in range(1, 10):
                    if check(arg, row, col, num):
                        arg[row, col] = num
                        solve_sudoku(arg)
                        arg[row, col] = 0
                return
        solved = arg.copy()
    solve_sudoku(sudoku)
    

    I don't know if it it is the best way to optimize the code, feedbacks are welcomed.