Search code examples
pythonsolversudoku

How to solve multiple sudokus in one file with python?


I am making a sudoku solver for school and one part of it, is that it needs to be able to solve multiple sudokus in a file. Currently it can solve one at a time, but how would I code it to solve multiple?

board = []
#open the file with puzzles in it
with open('project.txt','r') as file:
    for line in file:
         board.append(list(map(int,line.strip())))
    

#check puzzle for empty spaces
def solve(puzzle):
    find = find_empty(puzzle)
    if not find:
        return True
    else:
        row, col = find
    #go through 1 to 9 for each empty space
    for vertical in range(1,10):
        if valid(puzzle, vertical, (row, col)):
            puzzle[row][col] = vertical
            #continue to next empty space if number works
            if solve(puzzle):
                return True
            #backtrack until correct number is found
            puzzle[row][col] = 0

    return False


def valid(puzzle, num, pos):
    # Check each vertical row for correct numbers
    for vertical in range(len(puzzle[0])):
        if puzzle[pos[0]][vertical] == num and pos[1] != vertical:
            return False

    # Check each horizontal column for correct numbers
    for vertical in range(len(puzzle)):
        if puzzle[vertical][pos[1]] == num and pos[0] != vertical:
            return False

    # Check each 3x3 box for correct numbers
    box_x = pos[1] // 3
    box_y = pos[0] // 3

    for vertical in range(box_y*3, box_y*3 + 3):
        for horizontal in range(box_x * 3, box_x*3 + 3):
            #if any wrong numbers appear try again
            if puzzle[vertical][horizontal] == num and (vertical,horizontal) != pos:
                return False
    #if all numbers are correct solve puzzle
    return True

#formatting for how the final board should look
def print_board(puzzle):
    #open a new file for the answers to go into
    with open('files.txt', 'w') as file:
        #each row should have this formatting
        for vertical in range(len(puzzle)):
            if vertical % 3 == 0 and vertical != 0:
                print("- - - - - - - - - - - - - ", file=file)

            #each column should have this formatting
            for horizontal in range(len(puzzle[0])):
                if horizontal % 3 == 0 and horizontal != 0:
                    print(" | ", end="", file=file)

                if horizontal == 8:
                    print(puzzle[vertical][horizontal], file=file)
                else:
                    print(str(puzzle[vertical][horizontal]) + " ", end="", file=file)


def find_empty(puzzle):
    for vertical in range(len(puzzle)):
        for horizontal in range(len(puzzle[0])):
            if puzzle[vertical][horizontal] == 0:
                return (vertical, horizontal)  # row, col

    return None

#print the final solved puzzles 
solve(board)
print_board(board)

the file would be set up like this:

003020600
900305001
001806400
008102900
700000008
006708200
002609500
800203009
005010300

000900800
128006400
070800060
800430007
500000009
600079008
090004010
003600284
001007000

and we don't know how many puzzles there will be in the end. Thanks for any help!


Solution

  • The problem was that you were putting all the puzzles into a single board. Simply use the empty line (\n) between the puzzles as a delimiter to separate the board.

    Besides that, you should use if __name__ == "__main__": to

    protects users from accidentally invoking the script when they didn't intend to.

    if __name__ == "__main__":
        board_list = []
        board = []
        # open the file with puzzles in it
        with open('project.txt', 'r') as file:
            for line in file:
                # print(line)
                if line == "\n":
                    print("\\n detected")
                    board_list.append(board)
                    print(board_list)
                    board = []
                else:
                    #print("constructing board")
                    board.append(list(map(int, line.strip())))
            board_list.append(board)
    
        for i in range(len(board_list)):
            # print the final solved puzzles
            solve(board_list[i])
            print_board(board_list[i], i)
    

    I have also modified print_board() so that it write the puzzles into different files.

    def print_board(puzzle, index):
        # take the index of the board to write it to different files
        with open(f'files{index}.txt', 'w') as file: 
            # your code