0

In my code I cannot understand why python is returning a None at the end. I have tried to close every statement with Exit however I am still getting the None. Here is the output I am getting:

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

Here is my current code, could I kindly ask some assistance to identify where I am missing it:

import numpy as np
import copy

def sudoku_solver(sudoku):
    start_sudoku = copy.deepcopy(sudoku)
    duplicates(sudoku)
    solution(start_sudoku, sudoku)

def duplicates(sudoku):
    for r in range(9):
        line = (sudoku[r, :])
        nonzeros = [x for x in line.flatten() if x != 0]
        if (len(nonzeros) == len(set(nonzeros))) == False:
            array = [[-1 for i in range(9)] for j in range(9)]
            return (np.array(array))
    return

def solution(start_sudoku, sudoku):
    for y in range(9): 
        for x in range(9): 
            if sudoku[y][x] == 0:
                for n in range(1, 10): 
                    if possible(y, x, n):
                        sudoku[y][x] = n
                        solution(start_sudoku, sudoku)
                        sudoku[y][x] = 0 
                return
    if np.array_equal(sudoku, start_sudoku):
        array = [[-1 for i in range(9)] for j in range(9)]
        return np.array(array)
    return sudoku

your_solution = sudoku_solver(sudoku)
print(your_solution)
trincot
  • 317,000
  • 35
  • 244
  • 286
N K
  • 147
  • 7
  • To "remove" a None value being returned, return something else (or just don't print the returned None value). – mkrieger1 Sep 21 '21 at 08:49
  • an `exit()` directly after return will never hit and is useless. So my best guess whithout diving in too deep is that you hit the returns in solution, most likely in the if equal block – Eumel Sep 21 '21 at 08:50

3 Answers3

1

Your sudoku_solver function does not return anything, so the default is None, and then in the next line you print that None.

So remove all exit() from your functions, and remove the print you have in there, and make sure the function returns the solution:

def solution(sudoku):
    for y in range(9): 
        for x in range(9): 
            if sudoku[y][x] == 0:
                for n in range(1, 10): 
                    if possible(y, x, n):
                        sudoku[y][x] = n
                        result = solution(sudoku)
                        if result is not None:  # Get out of recursion: we have a solution!
                            return result
                        sudoku[y][x] = 0 
                return  # No solution here
    # If we get here, we have filled the sudoku completely: return it
    return sudoku

And return that also in sudoku_solver:

def sudoku_solver(sudoku):
    if duplicates(sudoku):
        return  # Not valid
    return solution(sudoku)

And duplicates should return a boolean: False = no duplicates, True = duplicates. I will leave that for you to do as it is not difficult to change the code in that way.

Addendum

From your attempts and edits to the question, it turns out you still have return statements without any value, or no return statements at all.

Here is a working version:

def possible(y, x, n):
    for i in range(0, 9):
        if sudoku[y][i] == n:
            return False
    for i in range(0, 9):
        if sudoku[i][x] == n:
            return False
    x0 = (x // 3) * 3
    y0 = (y // 3) * 3
    for i in range(0, 3):
        for j in range(0, 3):
            if sudoku[y0 + i][x0 + j] == n:
                return False
    return True

def duplicates(sudoku):
    for row in sudoku:
        row = [x for x in row if x]
        if (len(row) != len(set(row))):
            return True # there are duplicates
    for i in range(9):
        col = [row[i] for row in sudoku if row[i]]
        if (len(col) != len(set(col))):
            return True # there are duplicates
    for i in range(0, 9, 3):
        for j in range(0, 9, 3):
            box = sudoku[i][j:j+3] + sudoku[i+1][j:j+3] + sudoku[i+2][j:j+3]
            box = [x for x in box if x]
            if (len(box) != len(set(box))):
                return True # there are duplicates

def solution(sudoku):
    for y in range(9):
        for x in range(9):
            if sudoku[y][x] == 0:
                for n in range(1, 10):
                    if possible(y, x, n):
                        sudoku[y][x] = n
                        result = solution(sudoku)
                        if result is not None:
                            return result
                        sudoku[y][x] = 0
                return
    return sudoku

def sudoku_solver(sudoku):
    if duplicates(sudoku):
        raise ValueError("Invalid Sudoku: it has duplicates")
    return solution(sudoku)

sudoku = [[0, 0, 0, 3, 2, 8, 7, 1, 9],
 [3, 8, 7, 9, 1, 6, 4, 5, 2],
 [2, 9, 1, 4, 5, 7, 6, 3, 8],
 [5, 6, 3, 2, 9, 1, 8, 7, 4],
 [0, 7, 8, 6, 4, 5, 1, 2, 3],
 [1, 2, 4, 8, 7, 3, 5, 9, 6],
 [7, 3, 9, 5, 6, 4, 2, 8, 1],
 [8, 5, 6, 1, 3, 2, 9, 0, 7],
 [4, 1, 2, 7, 8, 9, 3, 6, 5]]
your_solution = sudoku_solver(sudoku)
print(your_solution)
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I removed all Exits and added the return, however I am still getting the None – N K Sep 21 '21 at 08:57
  • Yes, there are more problems. Updated answer. – trincot Sep 21 '21 at 08:58
  • I have tried everything even worked down the function to its very basic form and added return to each one, however I am still getting `None` – N K Sep 21 '21 at 12:21
  • Oh wait. You removed all the essential information from your question. That is not good. Please put that back, or this answer makes no sense anymore. I'll help you further if you can do that. – trincot Sep 21 '21 at 12:25
  • I added the information again as requested – N K Sep 21 '21 at 12:40
  • I rolled back your question to an earlier version, as there were functions missing you had in your original question. I have added a section to my answer. – trincot Sep 21 '21 at 13:05
  • Thank you, I however am still getting the following error: `ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()` – N K Sep 21 '21 at 13:25
  • ----> 3 your_solution = sudoku_solver(sudoku) – N K Sep 21 '21 at 13:27
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/237320/discussion-between-n-k-and-trincot). – N K Sep 21 '21 at 13:38
  • It seems like you used my code with numpy arrays. The code I posted is running just like it is. See it run on [repl.it](https://replit.com/@trincottrincots/sudokuqa) – trincot Sep 21 '21 at 13:51
  • However, if you use numpy, the `if result:` should become `if result is not None:`. I have updated my answer with that. – trincot Sep 21 '21 at 13:57
  • 1
    That works, thank you, thank you very much it is truly appreciated trincot – N K Sep 21 '21 at 14:04
0

As sudoku_solver function does not return anything your_solution will be None. The solved table is printed in solution function. At the end you are printing sudoku_solver which is None.

Murad Eliyev
  • 81
  • 1
  • 4
0

your_solution runs the function sodoku_solver(), which does not have a return statement. In python, a function with no return statement returns None. So by printing the your_solution, you are printing None.

If you want the solution returned in the function sodoku_solver(), return sodoku in solution() and change the last line in the sodoku_solver() function to return solution(start_sudoku, sudoku)