Python Forum
how to get the sudoku solver to work?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
how to get the sudoku solver to work?
#1
hello, I'm fairly new to python programming and I need help as I watched this video (https://www.youtube.com/watch?v=lK4N8E6uNr4) to create a sudoku solver. I've copied the code from it and the solver doesn't work. please can anyone help?

# import libraries here. Use the following ones only.
import time, sys, random

# add your implementation of the required functions here
def print_board(sudoku):
    for i in range(9):
        print(sudoku[i][0:3],'|',sudoku[i][3:6],'|',sudoku[i][6:9])
        if i==5 or i==2:
            print('-'*51 )
            
if __name__ == '__main__':

    # Don't change the layout of the following sudoku examples
    sudoku1 = [
        [' ', '1', '5', '4', '7', ' ', '2', '6', '9'],
        [' ', '4', '2', '3', '5', '6', '7', ' ', '8'],
        [' ', '8', '6', ' ', ' ', ' ', ' ', '3', ' '],
        ['2', ' ', '3', '7', '8', ' ', ' ', ' ', ' '],
        [' ', ' ', '7', ' ', ' ', ' ', ' ', '9', ' '],
        ['4', ' ', ' ', ' ', '6', '1', ' ', ' ', '2'],
        ['6', ' ', ' ', '1', ' ', ' ', ' ', ' ', ' '],
        [' ', ' ', '4', ' ', ' ', ' ', '1', ' ', '7'],
        [' ', ' ', ' ', ' ', '3', '7', '9', '4', ' '],
    ]
    sudoku2 = [
        [' ', ' ', ' ', '3', ' ', ' ', ' ', '7', ' '],
        ['7', '3', '4', ' ', '8', ' ', '1', '6', '2'],
        ['2', ' ', ' ', ' ', ' ', ' ', ' ', '3', '8'],
        ['5', '6', '8', ' ', ' ', '4', ' ', '1', ' '],
        [' ', ' ', '2', '1', ' ', ' ', ' ', ' ', ' '],
        [' ', ' ', '7', '8', ' ', ' ', '2', '5', '4'],
        [' ', '7', ' ', ' ', ' ', '2', '8', '9', ' '],
        [' ', '5', '1', '4', ' ', ' ', '7', '2', '6'],
        ['9', ' ', '6', ' ', ' ', ' ', ' ', '4', '5'],
    ]
    sudoku3 = [
        ['8', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
        [' ', ' ', '3', '6', ' ', ' ', ' ', ' ', ' '],
        [' ', '7', ' ', ' ', '9', ' ', '2', ' ', ' '],
        [' ', '5', ' ', ' ', ' ', '7', ' ', ' ', ' '],
        [' ', ' ', ' ', ' ', '4', '5', '7', ' ', ' '],
        [' ', ' ', ' ', '1', ' ', ' ', ' ', '3', ' '],
        [' ', ' ', '1', ' ', ' ', ' ', ' ', '6', '8'],
        [' ', ' ', '8', '5', ' ', ' ', ' ', '1', ' '],
        [' ', '9', ' ', ' ', ' ', ' ', '4', ' ', ' '],
    ]
    sudoku4 = [
        [' ', '4', '1', ' ', ' ', '8', ' ', ' ', ' '],
        ['3', ' ', '6', '2', '4', '9', ' ', '8', ' '],
        [' ', ' ', ' ', ' ', ' ', ' ', ' ', '7', ' '],
        [' ', ' ', ' ', '4', '7', ' ', '2', '1', ' '],
        ['7', ' ', ' ', '3', ' ', ' ', '4', ' ', '6'],
        [' ', '2', ' ', ' ', ' ', ' ', ' ', '5', '3'],
        [' ', ' ', '7', ' ', '9', ' ', '5', ' ', ' '],
        [' ', ' ', '3', ' ', '2', ' ', ' ', ' ', ' '],
        [' ', '5', '4', ' ', '6', '3', ' ', ' ', ' '],
    ]

    # make sure 'option=2' is used in your submission
    option = 2

    if option == 1:
        sudoku = sudoku1
    elif option == 2:
        sudoku = sudoku2
    elif option == 3:
        sudoku = sudoku3
    elif option == 4:
        sudoku = sudoku4
    else:
        raise ValueError('Invalid choice!')

#number is placed

def update_board(sudoku):
    
    find = find_space(sudoku)
    if not find:
        return True
    else:
        row,col = find

    for i in range(1,10):
        if is_valid(sudoku, i,(row, col)):
            sudoku[row][col] = i

            if update_board(sudoku):
                return True

            
            sudoku[row][col] = 0

    return False
    
# is the space valid 

def is_valid(sudoku, position, number):
    #space_x and space_y are within the box in the 
    space_x,space_y = 3*(position[1] // 3), 3*(position[0] // 3)
        
    for i in range(len(sudoku[0])):
        if sudoku[position[0]][i] == number and position[1] != i:
            return False

    for i in range(len(sudoku[0])):
        if sudoku[i][position[1]] == number and position[0] != i:
            return False

    for i in range(space_y,space_y + 3):
        for j in range(space_x,space_x+ 3):
            if sudoku[i][j] == number and (i,j) != position: 
                return False

    return True



# find empty_space 
def find_space(sudoku):
    
 # x and y are the coordinates of the grid. 
    for i in range(9):
        for j in range(9):
            #if the x and y have found an empty space, it is returned.
            if sudoku[i][j] == '':
                return (i,j)

    return None

# add code here to solve the sudoku
print_board(sudoku)
print("#"*51)
update_board(sudoku)
print_board(sudoku)
Larz60+ write Jan-08-2022, 06:38 PM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.

Attached Files

.py   sudoku.py (Size: 4.26 KB / Downloads: 187)
Reply
#2
'1' is not 1. You make a board of str but your solver expects numbers. I would change the board to hold numbers.
Reply
#3
Sudoku is solved by deduction. That is removing all wrong answers leaves only the right answer. Here's one way to go about it:
def print_board(sudoku):
	for i in range(9):
		print(sudoku[i][0:3],'|',sudoku[i][3:6],'|',sudoku[i][6:9])
		if i==5 or i==2:
			print('-'*51 )

def solve_sudoku_board (sudoku_board) :
	still_working_on_it = True
	while still_working_on_it :
		still_working_on_it = False
		for row in range (9) :
			for column in range (9) :
				if sudoku_board [row] [column] == ' ' :
					still_working_on_it = True
					test_numbers = [str (x) for x in range (1, 10, 1)]
					# Test across
					for number in sudoku_board [row] :
						if number in test_numbers :
							test_numbers.remove (number)
					# Test down
					for test_row in sudoku_board :
						if test_row [column] in test_numbers :
								test_numbers.remove (test_row [column])
					# Test square
					r_start = (row // 3) * 3
					r_end = r_start + 3
					c_start = (column // 3) * 3
					c_end = c_start + 3
					for square_row in range (r_start, r_end, 1) :
						for square_column in range (c_start, c_end, 1) :
							number = sudoku_board [square_row] [square_column]
							if number in test_numbers :
								test_numbers.remove (number)
					# If only one number is left, then that goes here
					if len (test_numbers) == 1 :
						sudoku_board [row] [column] = test_numbers [0]
	print_board (sudoku_board)

if __name__ == '__main__':
	sudoku2 = [
		[' ', ' ', ' ', '3', ' ', ' ', ' ', '7', ' '],
		['7', '3', '4', ' ', '8', ' ', '1', '6', '2'],
		['2', ' ', ' ', ' ', ' ', ' ', ' ', '3', '8'],
		['5', '6', '8', ' ', ' ', '4', ' ', '1', ' '],
		[' ', ' ', '2', '1', ' ', ' ', ' ', ' ', ' '],
		[' ', ' ', '7', '8', ' ', ' ', '2', '5', '4'],
		[' ', '7', ' ', ' ', ' ', '2', '8', '9', ' '],
		[' ', '5', '1', '4', ' ', ' ', '7', '2', '6'],
		['9', ' ', '6', ' ', ' ', ' ', ' ', '4', '5'],
	]

solve_sudoku_board (sudoku2)
Output:
['6', '8', '5'] | ['3', '2', '1'] | ['4', '7', '9'] ['7', '3', '4'] | ['9', '8', '5'] | ['1', '6', '2'] ['2', '1', '9'] | ['6', '4', '7'] | ['5', '3', '8'] --------------------------------------------------- ['5', '6', '8'] | ['2', '7', '4'] | ['9', '1', '3'] ['3', '4', '2'] | ['1', '5', '9'] | ['6', '8', '7'] ['1', '9', '7'] | ['8', '3', '6'] | ['2', '5', '4'] --------------------------------------------------- ['4', '7', '3'] | ['5', '6', '2'] | ['8', '9', '1'] ['8', '5', '1'] | ['4', '9', '3'] | ['7', '2', '6'] ['9', '2', '6'] | ['7', '1', '8'] | ['3', '4', '5']
Arya likes this post
Reply
#4
Tool1211's solution was mostly right. The problem was the solution was using numbers to fill the board spots, but the board was constructed using strings to fill the spots. As I mentioned in my reply, I would initialize the board with numbers like this.
    sudoku2 = [
        [0,0,0,3,0,0,0,7,0],
        [7,3,4,0,8,0,1,6,2],
        [2,0,0,0,0,0,0,3,8],
        [5,6,8,0,0,4,0,1,0],
        [0,0,2,1,0,0,0,0,0],
        [0,0,7,8,0,0,2,5,4],
        [0,7,0,0,0,2,8,9,0],
        [0,5,1,4,0,0,7,2,6],
        [9,0,6,0,0,0,0,4,5]
    ]
Not only is this a lot less typing to enter a board, but it prints prettier using (mostly) the same board print function.
Output:
[6, 8, 5] | [3, 2, 1] | [4, 7, 9] [7, 3, 4] | [9, 8, 5] | [1, 6, 2] [2, 1, 9] | [6, 4, 7] | [5, 3, 8] --------------------------------- [5, 6, 8] | [2, 7, 4] | [9, 1, 3] [3, 4, 2] | [1, 5, 9] | [6, 8, 7] [1, 9, 7] | [8, 3, 6] | [2, 5, 4] --------------------------------- [4, 7, 3] | [5, 6, 2] | [8, 9, 1] [8, 5, 1] | [4, 9, 3] | [7, 2, 6] [9, 2, 6] | [7, 1, 8] | [3, 4, 5]
Other than changing the board to initially contain numbers I think everything else works.

The code should be reorganized. All the functions should appear near the top and the only thing below if __name__ == '__main__': should be the code to run the solver. The program could also do with better variable names. "i" and "j" should almost never be used together. What do you think this is, basic? My version of Tool1211's code is below. I think all I changed was the board initialization and some variable names, reorganized the code layout, and added some better comments and docstrings.
"""
Sudoku puzzle solver.  Uses recursive solution to try all possible number combinations to fill the empty spots.
Returns the first valid solution
"""
def print_board(sudoku):
    """Print the board"""
    for row in range(9):
        print(sudoku[row][0:3],'|',sudoku[row][3:6],'|',sudoku[row][6:9])
        if row in (2, 5):
            print('-'*33 )

def update_board(sudoku):
    """Solve the board using recursion.  sudoku matrix is modified to contain the solution"""

    # Find first empty spot
    if (spot := find_empty(sudoku)) is None:
        return True  # No empty spots remaining.  Solved!!
    else:
        row, column = spot

    # Search for a number that fits in the empty spot
    for number in range(1, 10):
        if is_valid(sudoku, row, column, number):
            sudoku[row][column] = number
            if update_board(sudoku):  # Fill the next empty spot until no empty spots remain
                return True  # Puzzle solved

    # If we get here there were no valid numbers for this spot.  Set it back to empty
    sudoku[row][column] = 0

    # There are no solutions for the current board.  Undo the last spot and try again.
    return False

def is_valid(sudoku, row, column, number):
    """Return True if number can be placed in (row, column)"""

    # Look for matching number in the same row or column
    for i in range(9):
        if sudoku[i][column] == number or sudoku[row][i] == number:
            return False

    # Look for matching numbers in the same box
    row = row // 3 * 3
    column = column // 3 * 3
    for r in range(row, row+3):
        for c in range(column, column+3):
            if sudoku[r][c] == number:
                return False
    return True
 
def find_empty(sudoku):
    """Return row, column of first empty spot or None if no empty spots remain"""
    for row in range(9):
        try:
            # An empty spot contains 0
            return row, sudoku[row].index(0)
        except:
            pass
    return None

if __name__ == '__main__':
    sudoku = [
        [0,0,0,3,0,0,0,7,0],
        [7,3,4,0,8,0,1,6,2],
        [2,0,0,0,0,0,0,3,8],
        [5,6,8,0,0,4,0,1,0],
        [0,0,2,1,0,0,0,0,0],
        [0,0,7,8,0,0,2,5,4],
        [0,7,0,0,0,2,8,9,0],
        [0,5,1,4,0,0,7,2,6],
        [9,0,6,0,0,0,0,4,5]
    ]
    print_board(sudoku)
    print("#"*33)
    update_board(sudoku)
    print_board(sudoku)
Reply
#5
I don't know what it is that I like about Sudoku solvers. Maybe it's that they appear complex but are really quite simple. Here's a version that works with strings instead of numbers To highlight that I am using A-I instead of 1-9 for possible cell values. The solver uses a SudokuBoard class that handles things like printing the board and maintaining the cell values. It is a bit more efficient than the solver in the original post in that it only attempts available values in each cell instead of trying every value.
"""
Sudoku puzzle solver.  Uses recursive solution to try all possible number combinations to fill the empty spots.
Returns the first valid solution
"""
class SudokuBoard:
    """
    Board for playing Sudoku.
    Has a list of 81 cells, each cell representing an open spot in a Sudoku board.
    Each cell has a value.  Possible values are "-ABCDEFGHI" where "-" represents an
    open cell.
    """
    VALUES = list("ABCDEFGHI") # Values that can appear in cells
    EMPTY = "-"  # Empty cell marker

    def __init__(self, cells=None):
        self.cells = self.EMPTY*81 if cells is None else list(cells)

    def __str__(self):
        """Return pretty board string"""
        rows = []
        for row in range(9):
            r = self.cells[row*9:(row+1)*9]
            rows.append(f'{r[0]} {r[1]} {r[2]}   {r[3]} {r[4]} {r[5]}   {r[6]} {r[7]} {r[8]}')
            if row in (2, 5):
                rows.append("")
        return "\n".join(rows)

    def row(self, index):
        """Return values from the row that contains cells[index]"""
        index = index // 9 * 9
        return self.cells[index:index+9]

    def column(self, index):
        """Return values from the column that contains cells[index]"""
        index = index % 9
        return [self.cells[row + index] for row in range(0, 81, 9)]

    def square(self, index):
        """Return values from the square that contains cells[index]"""
        row = index // 27 * 3
        column = index % 9 // 3 * 3
        return [self.cells[r * 9 + c] for r in range(row, row+3) for c in range(column, column+3)]

    def open_options(self, index):
        """Return set of values that can be placed in cells[index]"""
        return set(self.VALUES) - set(self.row(index) + self.column(index) + self.square(index))

    def empty(self):
        """Return index of first empty cell or None if there are no empty cells"""
        try:
            return self.cells.index(self.EMPTY)
        except:
            return None

    def __setitem__(self, index, value):
        """Set cells[index] == value"""
        self.cells[index] = value

    def __getitem__(self, index):
        """Return cells[index]"""
        return self.cells[index]


def solver(board):
    """Recursive sudoku solver.  Uses SudokuBoard"""
    if (index := board.empty()) is None:
        return True  # No empty cells remain.  Solved!

    for value in board.open_options(index):
        board[index] = value
        if solver(board):
            return True

    # No solution for board[index].  Back up and try again
    board[index] = board.EMPTY
    return False

if __name__ == "__main__":
    board = SudokuBoard("---C---G-GCD-H-AFBB------CHEFH--D-A---BA-------GH--BED-G---BHI--EAD--GBFI-F----DE")
    print("\nStarting Board", board, sep="\n")
    if solver(board):
        print("\nSolution", board, sep="\n")
    else:
        print("No solution for board.")
Output:
Starting Board - - - C - - - G - G C D - H - A F B B - - - - - - C H E F H - - D - A - - - B A - - - - - - - G H - - B E D - G - - - B H I - - E A D - - G B F I - F - - - - D E Solution F H E C B A D G I G C D I H E A F B B A I F D G E C H E F H B G D I A C C D B A E I F H G A I G H C F B E D D G C E F B H I A H E A D I C G B F I B F G A H C D E
Reply
#6
(Jan-09-2022, 03:14 PM)BashBedlam Wrote: Sudoku is solved by deduction. That is removing all wrong answers leaves only the right answer. Here's one way to go about it:
def print_board(sudoku):
	for i in range(9):
		print(sudoku[i][0:3],'|',sudoku[i][3:6],'|',sudoku[i][6:9])
		if i==5 or i==2:
			print('-'*51 )

def solve_sudoku_board (sudoku_board) :
	still_working_on_it = True
	while still_working_on_it :
		still_working_on_it = False
		for row in range (9) :
			for column in range (9) :
				if sudoku_board [row] [column] == ' ' :
					still_working_on_it = True
					test_numbers = [str (x) for x in range (1, 10, 1)]
					# Test across
					for number in sudoku_board [row] :
						if number in test_numbers :
							test_numbers.remove (number)
					# Test down
					for test_row in sudoku_board :
						if test_row [column] in test_numbers :
								test_numbers.remove (test_row [column])
					# Test square
					r_start = (row // 3) * 3
					r_end = r_start + 3
					c_start = (column // 3) * 3
					c_end = c_start + 3
					for square_row in range (r_start, r_end, 1) :
						for square_column in range (c_start, c_end, 1) :
							number = sudoku_board [square_row] [square_column]
							if number in test_numbers :
								test_numbers.remove (number)
					# If only one number is left, then that goes here
					if len (test_numbers) == 1 :
						sudoku_board [row] [column] = test_numbers [0]
	print_board (sudoku_board)

if __name__ == '__main__':
	sudoku2 = [
		[' ', ' ', ' ', '3', ' ', ' ', ' ', '7', ' '],
		['7', '3', '4', ' ', '8', ' ', '1', '6', '2'],
		['2', ' ', ' ', ' ', ' ', ' ', ' ', '3', '8'],
		['5', '6', '8', ' ', ' ', '4', ' ', '1', ' '],
		[' ', ' ', '2', '1', ' ', ' ', ' ', ' ', ' '],
		[' ', ' ', '7', '8', ' ', ' ', '2', '5', '4'],
		[' ', '7', ' ', ' ', ' ', '2', '8', '9', ' '],
		[' ', '5', '1', '4', ' ', ' ', '7', '2', '6'],
		['9', ' ', '6', ' ', ' ', ' ', ' ', '4', '5'],
	]

solve_sudoku_board (sudoku2)
Output:
['6', '8', '5'] | ['3', '2', '1'] | ['4', '7', '9'] ['7', '3', '4'] | ['9', '8', '5'] | ['1', '6', '2'] ['2', '1', '9'] | ['6', '4', '7'] | ['5', '3', '8'] --------------------------------------------------- ['5', '6', '8'] | ['2', '7', '4'] | ['9', '1', '3'] ['3', '4', '2'] | ['1', '5', '9'] | ['6', '8', '7'] ['1', '9', '7'] | ['8', '3', '6'] | ['2', '5', '4'] --------------------------------------------------- ['4', '7', '3'] | ['5', '6', '2'] | ['8', '9', '1'] ['8', '5', '1'] | ['4', '9', '3'] | ['7', '2', '6'] ['9', '2', '6'] | ['7', '1', '8'] | ['3', '4', '5']




why is it only solving 1 problems not others?
Reply
#7
(Jan-09-2022, 03:14 PM)BashBedlam Wrote: Sudoku is solved by deduction. That is removing all wrong answers leaves only the right answer. Here's one way to go about it:
def print_board(sudoku):
	for i in range(9):
		print(sudoku[i][0:3],'|',sudoku[i][3:6],'|',sudoku[i][6:9])
		if i==5 or i==2:
			print('-'*51 )

def solve_sudoku_board (sudoku_board) :
	still_working_on_it = True
	while still_working_on_it :
		still_working_on_it = False
		for row in range (9) :
			for column in range (9) :
				if sudoku_board [row] [column] == ' ' :
					still_working_on_it = True
					test_numbers = [str (x) for x in range (1, 10, 1)]
					# Test across
					for number in sudoku_board [row] :
						if number in test_numbers :
							test_numbers.remove (number)
					# Test down
					for test_row in sudoku_board :
						if test_row [column] in test_numbers :
								test_numbers.remove (test_row [column])
					# Test square
					r_start = (row // 3) * 3
					r_end = r_start + 3
					c_start = (column // 3) * 3
					c_end = c_start + 3
					for square_row in range (r_start, r_end, 1) :
						for square_column in range (c_start, c_end, 1) :
							number = sudoku_board [square_row] [square_column]
							if number in test_numbers :
								test_numbers.remove (number)
					# If only one number is left, then that goes here
					if len (test_numbers) == 1 :
						sudoku_board [row] [column] = test_numbers [0]
	print_board (sudoku_board)

if __name__ == '__main__':
	sudoku2 = [
		[' ', ' ', ' ', '3', ' ', ' ', ' ', '7', ' '],
		['7', '3', '4', ' ', '8', ' ', '1', '6', '2'],
		['2', ' ', ' ', ' ', ' ', ' ', ' ', '3', '8'],
		['5', '6', '8', ' ', ' ', '4', ' ', '1', ' '],
		[' ', ' ', '2', '1', ' ', ' ', ' ', ' ', ' '],
		[' ', ' ', '7', '8', ' ', ' ', '2', '5', '4'],
		[' ', '7', ' ', ' ', ' ', '2', '8', '9', ' '],
		[' ', '5', '1', '4', ' ', ' ', '7', '2', '6'],
		['9', ' ', '6', ' ', ' ', ' ', ' ', '4', '5'],
	]

solve_sudoku_board (sudoku2)
Output:
['6', '8', '5'] | ['3', '2', '1'] | ['4', '7', '9'] ['7', '3', '4'] | ['9', '8', '5'] | ['1', '6', '2'] ['2', '1', '9'] | ['6', '4', '7'] | ['5', '3', '8'] --------------------------------------------------- ['5', '6', '8'] | ['2', '7', '4'] | ['9', '1', '3'] ['3', '4', '2'] | ['1', '5', '9'] | ['6', '8', '7'] ['1', '9', '7'] | ['8', '3', '6'] | ['2', '5', '4'] --------------------------------------------------- ['4', '7', '3'] | ['5', '6', '2'] | ['8', '9', '1'] ['8', '5', '1'] | ['4', '9', '3'] | ['7', '2', '6'] ['9', '2', '6'] | ['7', '1', '8'] | ['3', '4', '5']





is there a way to solve multiples sudoku? if there is can someone help please. Trying to find the Solution!!
Reply
#8
You need a way to input the initial board. You could input a string. Here I modify an earlier post to take a sudoku puzzle as input.
"""
Sudoku puzzle solver.  Uses recursive solution to try all possible number combinations to fill the empty spots.
Returns the first valid solution
"""
class SudokuBoard:
    """
    Board for playing Sudoku.
    Has a list of 81 cells, each cell representing an open spot in a Sudoku board.
    Each cell has a value.  Possible values are "-123456789" where "-" represents an
    open cell.
    """
    VALUES = list("123456789") # Values that can appear in cells
    EMPTY = "-"  # Empty cell marker

    def __init__(self, cells=None):
        self.cells = self.EMPTY*81 if cells is None else list(cells)

    def __str__(self):
        """Return pretty board string"""
        rows = []
        for i in range(0, 81, 9):
            r = self.cells[i:i+9]
            rows.append(f'{r[0]} {r[1]} {r[2]} | {r[3]} {r[4]} {r[5]} | {r[6]} {r[7]} {r[8]}')
            if i in (18, 45):
                rows.append("------+-------+------")
        return "\n".join(rows)

    def row(self, index):
        """Return values from the row that contains cells[index]"""
        index = index // 9 * 9
        return self.cells[index:index+9]

    def column(self, index):
        """Return values from the column that contains cells[index]"""
        index = index % 9
        return [self.cells[row + index] for row in range(0, 81, 9)]

    def square(self, index):
        """Return values from the square that contains cells[index]"""
        row = index // 27 * 3
        column = index % 9 // 3 * 3
        return [self.cells[r * 9 + c] for r in range(row, row+3) for c in range(column, column+3)]

    def open_options(self, index):
        """Return set of values that can be placed in cells[index]"""
        return set(self.VALUES) - set(self.row(index) + self.column(index) + self.square(index))

    def empty(self):
        """Return index of first empty cell or None if there are no empty cells"""
        try:
            return self.cells.index(self.EMPTY)
        except:
            return None

    def __setitem__(self, index, value):
        """Set cells[index] == value"""
        self.cells[index] = value

    def __getitem__(self, index):
        """Return cells[index]"""
        return self.cells[index]


def solver(board):
    """Recursive sudoku solver.  Uses SudokuBoard"""
    if (index := board.empty()) is None:
        return True  # No empty cells remain.  Solved!

    for value in board.open_options(index):
        board[index] = value
        if solver(board):
            return True

    # No solution for board[index].  Back up and try again
    board[index] = board.EMPTY
    return False

if __name__ == "__main__":
    # Examples.  Copy and paste as input.
    # -41--8---3-6249-8--------7----47-21-7--3--4-6-2-----53--7-9-5----3-2-----54-63---

    board = SudokuBoard(input("Enter board\n"))
    print("\nStarting Board", board, sep="\n")
    if solver(board):
        print("\nSolution", board, sep="\n")
    else:
        print("No solution for board.")
I provide an example input (copy and paste when asked for input).
Reply
#9
(Feb-03-2022, 02:26 PM)Arya Wrote: is there a way to solve multiples sudoku? if there is can someone help please. Trying to find the Solution!!
This will solve as many as you care to have if they are solvable.
def show_the_sudoku_board (board_name, puzzle_board, solved = True) :
	line = '\t ' + '-' * 29 
	if solved :
		print (f'\n{board_name} is now solved.\n' + line)
	else :
		print (f'\n\n\n\n\nNow working on {board_name}.\n' + line)
	for row in range (9) :
		print ('\t', puzzle_board [row] [0: 3], end = ' ')
		print (puzzle_board [row] [3: 6], puzzle_board [row] [6: 9],)
		if row in (2, 5, 8) : print (line)

def sudoku_puzzle_is_solved (sudoku_board) :
	for iteration in range (99) :
		for row in range (9) :
			for column in range (9) :
				if sudoku_board [row] [column] == 0 :
					test_number_list = [x for x in range (1, 10, 1)]
					r = row // 3 * 3
					c = column // 3 * 3
					tester = [sudoku_board [r][column] for r in range (9)]
					tester += sudoku_board [r] [c: c + 3]
					tester += sudoku_board [r + 1] [c: c + 3]
					tester += sudoku_board [r + 2] [c: c + 3]
					tester += sudoku_board [row]
					for number in tester :
						if number in test_number_list :
							test_number_list.remove (number)
					if len (test_number_list) == 1 :
						sudoku_board [row] [column] = test_number_list [0]
		tester = [sudoku_board[r][c] for r in range (9) for c in range (9)]
		if 0 not in tester : return True
	return False

def main_program_loop () :
	puzzle_count = len (sudoku_puzzles)
	for board_name, puzzle_board in sudoku_puzzles.items () :
		show_the_sudoku_board (board_name, puzzle_board, False)
		if sudoku_puzzle_is_solved (puzzle_board) :
			show_the_sudoku_board (board_name, puzzle_board, True)
		else :
			print (f'\n{board_name} is unsolvable!')

		while puzzle_count > 1 :
			puzzle_count -= 1
			print ('Would like to continue or quit now?')
			answer = input ('Enter C or Q : ').lower ()
			if answer [0] == 'c' : break 
			if answer [0] == 'q' : quit ()

if __name__ == '__main__' :
	from sudoku_puzzles import sudoku_puzzles
	main_program_loop ()
	print ("That was the last one. We're all Done now." )
And here is the file with the puzzles. There is a template at the bottom that will make it a little easier to enter more puzzles by hand.
_ = 0 # This makes the puzzle boards easier to read

sudoku_puzzles = {
	'Sudoku puzzle number one' : [
		[ _, _, _,  3, _, _,  _, 7, _ ],
		[ 7, 3, 4,  _, 8, _,  1, 6, 2 ],
		[ 2, _, _,  _, _, _,  _, 3, 8 ],
 
		[ 5, 6, 8,  _, _, 4,  _, 1, _ ],
		[ _, _, 2,  1, _, _,  _, _, _ ],
		[ _, _, 7,  8, _, _,  2, 5, 4 ],

		[ _, 7, _,  _, _, 2,  8, 9, _ ],
		[ _, 5, 1,  4, _, _,  7, 2, 6 ],
		[ 9, _, 6,  _, _, _,  _, 4, 5 ]],

	'Sudoku puzzle number two' : [
		[ 1, _, 3,  2, _, _,  _, 8, _ ],
		[ 2, 6, _,  _, 8, _,  _, _, _ ],
		[ _, _, _,  5, _, 9,  6, _, 2 ],

		[ _, _, _,  3, 7, _,  5, 4, _ ],
		[ _, 1, 5,  _, _, _,  _, _, 6 ],
		[ 3, _, 8,  _, _, 5,  1, _, _ ],

		[ 5, _, _,  _, 6, _,  7, 9, _ ],
		[ _, _, 1,  4, _, 7,  _, _, 3 ],
		[ 6, _, 4,  _, 3, _,  _, _, 1 ]],

	'Sudoku puzzle number three' : [
		[ _, _, 6,  4, 8, _,  _, 1, _ ],
		[ _, 9, 5,  _, _, _,  8, _, 6 ],
		[ 4, _, _,  6, _, _,  7, 9, _ ],

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

		[ 5, _, 2,  _, 4, _,  _, 7, _ ],
		[ _, _, 7,  5, 2, _,  _, _, 8 ],
		[ _, _, 8,  _, 6, _,  _, 2, 5 ]],

	'Sudoku puzzle number four' : [
		[ 8, 9, _,  7, 3, _,  _, _, _ ],
		[ _, 2, _,  _, _, _,  _, 8, _ ],
		[ _, _, _,  1, 9, _,  2, 3, 6 ],

		[ 9, _, 2,  _, _, _,  7, 5, _ ],
		[ _, _, _,  6, 2, 5,  3, 9, _ ],
		[ _, _, 1,  9, _, _,  _, _, _ ],

		[ _, _, 5,  _, _, 9,  _, 1, _ ],
		[ _, 4, 8,  3, 6, 1,  5, 2, 9 ],
		[ _, 1, _,  8, _, _,  _, _, 3 ]]
}

# Template to aid creating new puzzle boards
{'template' : [
		[ _, _, _,  _, _, _,  _, _, _ ],
		[ _, _, _,  _, _, _,  _, _, _ ],
		[ _, _, _,  _, _, _,  _, _, _ ],

		[ _, _, _,  _, _, _,  _, _, _ ],
		[ _, _, _,  _, _, _,  _, _, _ ],
		[ _, _, _,  _, _, _,  _, _, _ ],

		[ _, _, _,  _, _, _,  _, _, _ ],
		[ _, _, _,  _, _, _,  _, _, _ ],
		[ _, _, _,  _, _, _,  _, _, _ ]]}
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Sudoku making with base Python wep 1 1,054 Oct-18-2023, 04:37 AM
Last Post: deanhystad
  Equation Solver cur 1 2,395 Nov-05-2018, 03:28 PM
Last Post: Gribouillis

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020