Created
July 22, 2022 01:00
-
-
Save alexover1/68799c953d30a348dd94fcb8720d41ed to your computer and use it in GitHub Desktop.
Sudoku solver in Go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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