Sudoku is a popular number-placement puzzle where the objective is to fill a 9x9 grid with digits so that each column, each row, and each of the nine 3x3 subgrids (also known as "boxes") contains all of the digits from 1 to 9. The puzzle starts with some cells already filled in, and the player must fill in the remaining cells.
In this tutorial, we will explore how to solve a Sudoku puzzle using the backtracking algorithm. Backtracking is a powerful technique used in computer science for solving constraint satisfaction problems by incrementally building candidates and abandoning a candidate as soon as it determines that the candidate cannot possibly be completed to a valid solution.
Before diving into the implementation, let's break down the problem:
Backtracking is a recursive algorithm that attempts to build a solution incrementally, one piece at a time. If it determines that the current path cannot lead to a valid solution, it backtracks and tries a different path.
The base case for the recursion is when there are no more empty cells left in the grid, indicating that the puzzle has been solved successfully.
Let's implement the Sudoku solver using backtracking in Python. We'll use a 2D list to represent the Sudoku grid.
def is_valid(board, row, col, num):
# Check if 'num' is not in the current row
for x in range(9):
if board[row][x] == num:
return False
# Check if 'num' is not in the current column
for x in range(9):
if board[x][col] == num:
return False
# Check if 'num' is not in the current 3x3 subgrid
start_row = row - row % 3
start_col = col - col % 3
for i in range(3):
for j in range(3):
if board[i + start_row][j + start_col] == num:
return False
return True
def solve_sudoku(board):
empty = find_empty_location(board)
if not empty:
return True # Puzzle solved
row, col = empty
for num in range(1, 10):
if is_valid(board, row, col, num):
board[row][col] = num
if solve_sudoku(board):
return True
board[row][col] = 0 # Backtrack
return False
def find_empty_location(board):
for i in range(9):
for j in range(9):
if board[i][j] == 0:
return (i, j)
return None
# Example usage
sudoku_board = [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]
]
if solve_sudoku(sudoku_board):
print("Sudoku solved successfully!")
else:
print("No solution exists.")
# Print the solved Sudoku board
for row in sudoku_board:
print(row)
is_valid function ensures that all Sudoku constraints are respected.The Sudoku solver implemented using backtracking is a classic example of how recursive algorithms can be used to solve constraint satisfaction problems. While it may not be the most efficient solution for very large puzzles, it provides a clear and understandable approach to solving Sudoku puzzles programmatically. By understanding the constraints and applying backtracking effectively, you can tackle similar problems in data structures and algorithms.