Skip to content

Instantly share code, notes, and snippets.

@alexover1
Created July 22, 2022 01:00
Show Gist options
  • Save alexover1/68799c953d30a348dd94fcb8720d41ed to your computer and use it in GitHub Desktop.
Save alexover1/68799c953d30a348dd94fcb8720d41ed to your computer and use it in GitHub Desktop.
Sudoku solver in Go
package main
import (
"fmt"
"time"
)
const BOARD_SIZE int = 9
const BOX_SIZE int = 3
type Axis = []int
var puzzle = [BOARD_SIZE][BOARD_SIZE]int{
{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}}
func MakeRange(min, max int) []int {
a := make([]int, max-min+1)
for i := range a {
a[i] = min + i
}
return a
}
func remove[T any](s []T, i int) []T {
s[i] = s[len(s)-1]
return s[:len(s)-1]
}
func indexof[T comparable](s []T, e T) int {
for i, a := range s {
if a == e {
return i
}
}
return -1
}
func Row(number int) Axis {
return puzzle[number][:]
}
func Column(number int) Axis {
var column Axis
for _, row := range puzzle {
column = append(column, row[number])
}
return column
}
func Box(row_number, col_number int) Axis {
start_y := col_number / BOX_SIZE * BOX_SIZE
start_x := row_number / BOX_SIZE * BOX_SIZE
if start_x < 0 {
start_x = 0
}
if start_y < 0 {
start_y = 0
}
var box Axis
for i := start_x; i < BOX_SIZE+start_x; i++ {
for _, elem := range puzzle[i][start_y : start_y+BOX_SIZE] {
box = append(box, elem)
}
}
return box
}
func Possibilities(row_number, col_number int) Axis {
result := MakeRange(1, 9)
row := Row(row_number)
col := Column(col_number)
box := Box(row_number, col_number)
// len(row) == len(col) == len(box)
for it := range row {
if i := indexof(result, row[it]); i != -1 {
result = remove(result, i)
}
if i := indexof(result, col[it]); i != -1 {
result = remove(result, i)
}
if i := indexof(result, box[it]); i != -1 {
result = remove(result, i)
}
}
return result
}
func Solve() int {
unsolved := true
iterations := 0
for unsolved {
unsolved = false
iterations++
for row_n, row := range puzzle {
for col_n, col := range row {
if col == 0 {
unsolved = true
if ps := Possibilities(row_n, col_n); len(ps) == 1 {
puzzle[row_n][col_n] = ps[0]
}
}
}
}
}
return iterations
}
func PrintPuzzle() {
border := "------+------+------"
for y, row := range puzzle {
if y%3 == 0 {
fmt.Println(border)
}
for x, col := range row {
if x != 0 {
if x%3 == 0 {
fmt.Print(" |")
} else {
fmt.Print(" ")
}
}
if col == 0 {
fmt.Print(".")
} else {
fmt.Print(col)
}
}
fmt.Println()
}
fmt.Println(border)
}
func main() {
start := time.Now()
iterations := Solve()
elapsed := time.Since(start)
PrintPuzzle()
fmt.Printf("\n[INFO] Took %v iterations\n", iterations)
fmt.Println("[INFO] Finished in", elapsed)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment