0

I have reviewed multiple questions regarding similar problems but have not been able to find a solution. I have to write a script for solving and displaying a sudoku puzzle in a text file. If there is no possible solution, it should return None, otherwise it should print the formatted and solved puzzle. My issue is that my solve() function always returns None, even for puzzles with simple solutions. I have tried to debug by following the logic and reviewing my syntax but I fear I am making a simple mistake I cannot see. My functions are

def load_puzzle(path):
    with open(path) as fin:
        contents = fin.read()
    
    lines = contents.split('\n')
    puzzle = []
    for i in lines:
        token_strings = i.split(' ')
        token_ints = [int(x) for x in token_strings]
        puzzle.append(token_ints)
    return puzzle

def display_puzzle(puzzle):
    for i in range(9):
        if i == 0 or i == 3 or i == 6:
            print('+-------+-------+-------+')
        row = '| '
        for j in range(9):
            if puzzle[i][j] == 0:
                row = row + '. '
            else:
                row = row + str(puzzle[i][j]) + ' '
            if j==2 or j==5 or j==8:
                row = row + '| '
        print(row)
    print('+-------+-------+-------+')
    
def get_next(row, col):
    if col < 8:
        #print('inside get_next') #DEBUG
        return row, col+1
    elif col == 8 and row < 8:
        return row+1, 0
    elif col == 8 and row == 8:
        return None, None
    
def copy_puzzle(puzzle):
    new_puzzle = []
    for i in puzzle:
        new_puzzle.append(i.copy())
    return new_puzzle

def get_options(puzzle, row, col):
    if puzzle[row][col] > 0:
        return None
    used = []
    for i in puzzle[row]:
        if i > 0:
            used.append(i)
    for i in range(9): 
        if puzzle[i][col] > 0:
            used.append(puzzle[i][col])
    start_row = 3*int(row/3) 
    start_col = 3*int(col/3)
    for i in range(2):
        for j in range(2):
            if puzzle[start_row + i][start_col +j] > 0:
                used.append(puzzle[start_row + i][start_col +j])
    options = []
    for i in range(1, 10):
        if i not in used:
            options.append(i)
    return options

def solve(puzzle, row=0, col=0):
    if puzzle[row][col] != 0:
        #print("here") # debuggin
        next_row, next_col = get_next(row, col)
        #print(next_row, next_col) # debugging
        if next_row is None:
            return puzzle
        else:
            solve(puzzle, next_row, next_col)
    
    if puzzle[row][col] == 0:
       
       # print("there") # debuggin
        
        options = get_options(puzzle, row, col)
        
        #print(options) #debuggin
        
        if options == []:
            return None
        for i in options:
                new_puzzle = copy_puzzle(puzzle)
                new_puzzle[row][col] = i
        
               # display_puzzle(new_puzzle) #debuggin
                
                result = solve(new_puzzle, row, col)
                if result is not None:
                    return result

The commented out print() functions are ones I used to follow the loops to make sure the functions were operating as intended. As far as I can tell they were, but with so many loops, Jupyter Notebook began to print over itself and the display became indecipherable, as well as the making the function have an unreasonable resolution time.

The initial test puzzle is a .txt file containing:

5 0 0 0 0 0 0 0 0
0 9 0 7 0 0 8 0 0
0 0 0 0 3 0 0 7 0
6 0 1 0 0 0 9 8 0
0 0 0 6 0 0 0 0 0
0 0 9 0 0 0 7 0 1
0 0 0 0 0 8 1 9 0
0 4 0 5 0 1 0 0 8
0 7 0 3 0 6 0 4 0
MArBel
  • 3
  • 3
  • The recursive call to `solve` returns something, but you ignore whatever that is. – chepner Aug 21 '21 at 16:31
  • I have since altered solve to return display_puzzle(result) but it is now displaying incorrect solutions. I think that is a step forward but I am not sure. – MArBel Aug 21 '21 at 16:39
  • It should return the solution – MArBel Aug 21 '21 at 17:12
  • `else: solve(puzzle, next_row, next_col)` should be `else: return solve(puzzle, next_row, next_col)` – Stef Aug 21 '21 at 19:04

1 Answers1

0

Solved:

Missing return statement before solve(puzzle, next_row, next_col).

also ranges for cell check in get_options() should be set to 3 instead of 2.

MArBel
  • 3
  • 3