Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

summit sudoku slover #49

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions dfs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package main

// dfs flattens the 2D board array into a 1D array and recursively fills in numbers.
// n: The index in the flattened 1D array.
// rows: The set of numbers already used in each row when examining position n.
// cols: The set of numbers already used in each column when examining position n.
// grids: The set of numbers already used in each grid (3x3 grid) when examining position n.
func dfs(board [][]int, n int, rows []int, cols []int, grids []int) bool {
// Recursive end condition: if n is equal to the total number of cells, all positions are filled.
if n == len(board)*len(board) {
return true
}
// Locate the row and column based on n.
var i, j = n / len(board), n % len(board)
// If the current position is already filled, skip to the next position.
if board[i][j] != 0 {
return dfs(board, n+1, rows, cols, grids)
}
// Attempt to fill the current position with numbers 1 to 9.
for k := 1; k <= 9; k++ {
var bit = 1 << k
// Check if the number is not yet used in the corresponding row, column, and grid.
if unused := rows[i]&bit == 0 && cols[j]&bit == 0 && grids[i/3*3+j/3]&bit == 0; unused {
// Mark the number as used in the row, column, and grid.
rows[i] |= bit
cols[j] |= bit
grids[i/3*3+j/3] |= bit
// Continue to fill the next position.
if dfs(board, n+1, rows, cols, grids) {
// If the recursion returns true, it means all subsequent positions are correctly filled,
// so we can fill the current position.
board[i][j] = k
return true
} else {
// If the recursion returns false, it means subsequent positions failed to fill,
// so the current number is invalid and we need to try the next number.
// Before trying the next number, we need to unmark the current number in the row, column, and grid.
rows[i] &= ^bit
cols[j] &= ^bit
grids[i/3*3+j/3] &= ^bit
}
}
}
// If none of the numbers 1 to 9 can be filled in the current position, the Sudoku puzzle is unsolvable at this configuration.
return false
}
22 changes: 22 additions & 0 deletions error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import (
"fmt"
)

const (
ERR_INVALID_SUDOKU_SIZE = -000001 // sudoku size is invalid
ERR_INVALID_SUDOKU = -000002 // sudoku cannot be solved
)

func reportErr(errCode int) {
var errInfo string
switch errCode {
case ERR_INVALID_SUDOKU_SIZE:
errInfo = "Sudoku size is invalid"
case ERR_INVALID_SUDOKU:
errInfo = "Sudoku is unsolvable"
}

fmt.Printf("%v with Error code:%v", errInfo, errCode)
}
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
module sudoku

go 1.21.5
36 changes: 36 additions & 0 deletions sudoku.go
Original file line number Diff line number Diff line change
@@ -1 +1,37 @@
package main

const (
LEGAL_SUDOKU_SIZE = 9 // legal size of the input sudoku

)

func SolveSudoku(board [][]int) [][]int {

// check input size
if len(board) != LEGAL_SUDOKU_SIZE {
reportErr(ERR_INVALID_SUDOKU_SIZE)
return board
}
for _, row := range board {
if len(row) != LEGAL_SUDOKU_SIZE {
reportErr(ERR_INVALID_SUDOKU_SIZE)
return board
}
}

// Initialize slices to keep track of the numbers used in each row, column, and zone (3x3 grid),
// storing this information as bits.
var rows, cols, grids = make([]int, 9), make([]int, 9), make([]int, 9)
for i := range board {
for j := range board[i] {
if board[i][j] != 0 {
var bit = 1 << board[i][j]
rows[i] |= bit // Mark the bit as used in the row.
cols[j] |= bit // Mark the bit as used in the column.
grids[i/3*3+j/3] |= bit // Mark the bit as used in the zone.
}
}
}
dfs(board, 0, rows, cols, grids)
return board
}
Loading