From 14043fc23cbf1f441c0bc073fe615aa18f70255e Mon Sep 17 00:00:00 2001 From: Zaki Rangwala Date: Mon, 29 Jan 2024 22:01:33 -0500 Subject: [PATCH 1/3] stable --- sudoku.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/sudoku.go b/sudoku.go index 06ab7d0..32bcad4 100644 --- a/sudoku.go +++ b/sudoku.go @@ -1 +1,65 @@ package main + +/// SolveSudoku solves the Sudoku puzzle using backtracking algorithm +func SolveSudoku(grid [][]int) [][]int { + if solve(grid) { + return grid + } + return nil +} + +// solve is the recursive function that implements the backtracking +func solve(grid [][]int) bool { + emptyRow, emptyCol, found := findEmptySpot(grid) + if !found { + return true + } + // Use a frequency count heuristic to prioritize the numbers that are most likely to lead to a solution + counts := make([]int, 9) + for i := 0; i < 9; i++ { + for j := 0; j < 9; j++ { + counts[grid[i][j]-1]++ + } + } + for num := 1; num <= 9; num++ { + if counts[num-1] < 9 && isValid(grid, emptyRow, emptyCol, num) { + grid[emptyRow][emptyCol] = num + if solve(grid) { + return true + } + // Reset the spot and try the next number + grid[emptyRow][emptyCol] = 0 + } + } + return false +} + +// isValid checks if num can be placed at grid[row][col] +func isValid(grid [][]int, row int, col int, num int) bool { + for i := 0; i < 9; i++ { + if grid[row][i] == num || grid[i][col] == num { + return false + } + } + startRow, startCol := row-row%3, col-col%3 + for i := 0; i < 3; i++ { + for j := 0; j < 3; j++ { + if grid[i+startRow][j+startCol] == num { + return false + } + } + } + return true +} + +// findEmptySpot finds an empty spot in the grid and returns its coordinates +func findEmptySpot(grid [][]int) (int, int, bool) { + for i := 0; i < 9; i++ { + for j := 0; j < 9; j++ { + if grid[i][j] == 0 { + return i, j, true + } + } + } + return 0, 0, false +} \ No newline at end of file From 96ef1cce1007379f3218040f2c645e974f4d70a0 Mon Sep 17 00:00:00 2001 From: Zaki Rangwala Date: Mon, 29 Jan 2024 22:03:24 -0500 Subject: [PATCH 2/3] fix error + implement backtracing algorithm --- sudoku.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/sudoku.go b/sudoku.go index 32bcad4..20c715f 100644 --- a/sudoku.go +++ b/sudoku.go @@ -1,6 +1,6 @@ package main -/// SolveSudoku solves the Sudoku puzzle using backtracking algorithm +// SolveSudoku solves the Sudoku puzzle using backtracking algorithm func SolveSudoku(grid [][]int) [][]int { if solve(grid) { return grid @@ -14,20 +14,12 @@ func solve(grid [][]int) bool { if !found { return true } - // Use a frequency count heuristic to prioritize the numbers that are most likely to lead to a solution - counts := make([]int, 9) - for i := 0; i < 9; i++ { - for j := 0; j < 9; j++ { - counts[grid[i][j]-1]++ - } - } for num := 1; num <= 9; num++ { - if counts[num-1] < 9 && isValid(grid, emptyRow, emptyCol, num) { + if isValid(grid, emptyRow, emptyCol, num) { grid[emptyRow][emptyCol] = num if solve(grid) { return true } - // Reset the spot and try the next number grid[emptyRow][emptyCol] = 0 } } From db2d7afec5c386c44b54eaf945a8bc21f16a1b31 Mon Sep 17 00:00:00 2001 From: Zaki Rangwala Date: Mon, 29 Jan 2024 22:15:52 -0500 Subject: [PATCH 3/3] optimize program --- sudoku.go | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/sudoku.go b/sudoku.go index 20c715f..ce41d7b 100644 --- a/sudoku.go +++ b/sudoku.go @@ -1,6 +1,8 @@ package main -// SolveSudoku solves the Sudoku puzzle using backtracking algorithm +// SolveSudoku(grid) : solves the sudoku puzzle using a backtracking algorithm +// returns the solved puzzle if it exists, nil otherwise +// asserts: len(grid) == 9, len(grid[i]) == 9 for 0 <= i < 9 func SolveSudoku(grid [][]int) [][]int { if solve(grid) { return grid @@ -8,7 +10,9 @@ func SolveSudoku(grid [][]int) [][]int { return nil } -// solve is the recursive function that implements the backtracking +// solve(grid) recursively backtraces to solve puzzle +// returns true if puzzle is solved, false otherwise +// asserts: len(grid) == 9, len(grid[i]) == 9 for 0 <= i < 9 func solve(grid [][]int) bool { emptyRow, emptyCol, found := findEmptySpot(grid) if !found { @@ -26,32 +30,53 @@ func solve(grid [][]int) bool { return false } -// isValid checks if num can be placed at grid[row][col] +// isValid(grid, row, col, num) checks if num can be placed at the square grid[row][col] +// returns true if num can be placed, false otherwise +// asserts: len(grid) == 9, len(grid[i]) == 9 for 0 <= i < 9 func isValid(grid [][]int, row int, col int, num int) bool { + blockRow, blockCol := row-row%3, col-col%3 for i := 0; i < 9; i++ { if grid[row][i] == num || grid[i][col] == num { return false } - } - startRow, startCol := row-row%3, col-col%3 - for i := 0; i < 3; i++ { - for j := 0; j < 3; j++ { - if grid[i+startRow][j+startCol] == num { - return false - } + if grid[blockRow+i/3][blockCol+i%3] == num { + return false } } return true } -// findEmptySpot finds an empty spot in the grid and returns its coordinates +// findEmptySpot(grid) finds an empty spot in the grid and returns its coordinates +// returns true if an empty spot is found, false otherwise +// asserts: len(grid) == 9, len(grid[i]) == 9 for 0 <= i < 9 func findEmptySpot(grid [][]int) (int, int, bool) { + minOptions := 10 + minRow := -1 + minCol := -1 for i := 0; i < 9; i++ { for j := 0; j < 9; j++ { if grid[i][j] == 0 { - return i, j, true + numOptions := countOptions(grid, i, j) + if numOptions < minOptions { + minOptions = numOptions + minRow = i + minCol = j + } } } } - return 0, 0, false + return minRow, minCol, minRow != -1 +} + +// countOptions(grid, row, col) counts the number of options for a square in the grid +// returns the number of options +// asserts: len(grid) == 9, len(grid[i]) == 9 for 0 <= i < 9 +func countOptions(grid [][]int, row int, col int) int { + options := 0 + for num := 1; num <= 9; num++ { + if isValid(grid, row, col, num) { + options++ + } + } + return options } \ No newline at end of file