Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy all of the following rules:
1-9
must occur exactly once in each row.1-9
must occur exactly once in each column.1-9
must occur exactly once in each of the 9 3x3
sub-boxes of the grid.The '.'
character indicates empty cells.
For example:
Input:
board = [
["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
Output:
[
["5","3","4","6","7","8","9","1","2"],
["6","7","2","1","9","5","3","4","8"],
["1","9","8","3","4","2","5","6","7"],
["8","5","9","7","6","1","4","2","3"],
["4","2","6","8","5","3","7","9","1"],
["7","1","3","9","2","4","8","5","6"],
["9","6","1","5","3","7","2","8","4"],
["2","8","7","4","1","9","6","3","5"],
["3","4","5","2","8","6","1","7","9"]
]
Constraints:
board.length == 9
board[i].length == 9
board[i][j]
is a digit or '.'
.## Solving Sudoku Puzzles with Backtracking
This program solves Sudoku puzzles by implementing a backtracking algorithm. The core idea is to iterate through the empty cells and try filling them with numbers 1-9. If a number violates Sudoku rules, we backtrack and try another number. If we find a valid number, we move to the next empty cell and repeat the process. The algorithm continues until the entire board is filled according to Sudoku rules, or we have exhausted all possibilities, implying no solution exists.
### Code:
```python
def solve_sudoku(board):
"""Solves a Sudoku puzzle using backtracking."""
def find_empty_location(board):
for i in range(9):
for j in range(9):
if board[i][j] == ".":
return (i, j)
return None
def is_valid(board, num, pos):
# Check row
for i in range(9):
if board[pos[0]][i] == num and pos[1] != i:
return False
# Check column
for i in range(9):
if board[i][pos[1]] == num and pos[0] != i:
return False
# Check 3x3 box
box_x = pos[1] // 3
box_y = pos[0] // 3
for i in range(box_y * 3, box_y * 3 + 3):
for j in range(box_x * 3, box_x * 3 + 3):
if board[i][j] == num and (i,j) != pos:
return False
return True
def solve():
empty_location = find_empty_location(board)
if not empty_location:
return True # No more empty locations, puzzle solved
row, col = empty_location
for num in range(1, 10):
num = str(num)
if is_valid(board, num, (row, col)):
board[row][col] = num
if solve():
return True
board[row][col] = "." # Backtrack
return False # No solution found for this empty location
solve()
return board
# Example Usage:
board = [
["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
solved_board = solve_sudoku(board)
for row in solved_board:
print(row)
The most straightforward approach would be to try every possible combination of numbers in the empty cells. This means filling the first empty cell with a 1, checking if the board is valid, then trying 2, 3, up to 9. If none of them are valid, you backtrack. If a number is valid, you move on to the next empty cell and repeat the process. The issue with this method is that it's incredibly inefficient due to the massive number of possible combinations.
The backtracking algorithm significantly reduces the search space. Instead of exhaustively checking all combinations, it intelligently explores possibilities. When a conflict (invalid placement) is detected, the algorithm immediately backtracks to the previous decision point, avoiding the exploration of entire sub-trees of invalid combinations. This pruning strategy makes the backtracking algorithm much more efficient than a brute-force approach.
The time complexity of the backtracking algorithm for solving Sudoku is difficult to precisely determine, but it's often approximated as O(9^E), where E is the number of empty cells. Here's why:
While the O(9^E) is a common approximation, the actual runtime depends heavily on the structure of the puzzle and the effectiveness of the constraints in reducing the search space. Well-designed Sudoku puzzles that provide more initial clues can be solved much faster.
The space complexity of the backtracking algorithm is primarily determined by the call stack during the recursive calls. Here's the analysis:
Therefore, the space complexity can be estimated as O(E), where E is the number of empty cells. In the worst case, E could be close to 81 (all cells empty), but in typical Sudoku puzzles, E is significantly smaller.
False
.