Search code examples
pythonrecursionbacktrackingsudoku

How to stop a recursive function from executing at a certain point in Python


Following this code, I'm trying to write a piece to find out if a sudoku has one or more than one solutions (we can safely assume that there is at least one solution for sure). This is the code:

grid = []
while True:
    row = list(input('Row: '))
    ints = []

    for n in row:
        ints.append(int(n))
    grid.append(ints)

    if len(grid) == 9:
        break


def possible(x, y, n):
    for i in range(0, 9):
        if grid[i][x] == n and i != y: # Checks for number (n) in X columns
            return False

    for i in range(0, 9):
        if grid[y][i] == n and i != x: # Checks for number (n) in X columns
            return False

    x0 = (x // 3) * 3
    y0 = (y // 3) * 3
    for X in range(x0, x0 + 3):
        for Y in range(y0, y0 + 3):  # Checks for numbers in box(no matter the position, it finds the corner)
            if grid[Y][X] == n:
                return False    
    return True


def solve():
    global grid
    for y in range(9):
        for x in range(9):
            if grid[y][x] == 0:
                for n in range(1, 10):
                    if possible(x, y, n):
                        grid[y][x] = n
                        solve()
                        grid[y][x] = 0
                return
    print(grid)


solve()

The problem is, this code will print out all of the solutions for a given sudoku, even if the puzzle has, say, 100 solutions. I am not interested in that. I just want to know if there is more than one answer or not. So basically, I want the solve function to stop immediately once more than one solution is found, and inform the user about that. How can I do that? How can I stop the code to go all the way down to the very last solution?


Solution

  • A recursive solve function could be rewritten as a generator:

    # print(solution) --> yield solution
    # solve(...) --> yield from solve(...)
    

    Then to collect all solutions:

    for s in solve(...):
        print(s)
    

    and finally to abort after N (e.g. 2) solutions:

    for i,s in enumerate(solve(...), start=1):
        print(s)
        if i >= N:
            has_N_solutions = True
            break
    else:
        # else = no break
        has_N_solutions = False