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

Samuel Adeoye - Sudoku Algorithm #88

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
68 changes: 67 additions & 1 deletion sudoku.go
Original file line number Diff line number Diff line change
@@ -1 +1,67 @@
package main
package sudoku


const BOARD_SIZE = 9
const SMALL_GRID_SIZE = 3


func isPossible(grid [][]int, row int, col int, n int) bool {
// Check to see if number is unique for row and column
for i:=0; i<BOARD_SIZE; i++ {
if grid[row][i] == n || grid[i][col] == n {
return false
}
}

offsetRow := (row/SMALL_GRID_SIZE)*SMALL_GRID_SIZE
offsetCol := (col/SMALL_GRID_SIZE)*SMALL_GRID_SIZE

// Check to see if number is unique for 3x3 subgrid
for i:=0; i<SMALL_GRID_SIZE; i++ {
for j:=0; j<SMALL_GRID_SIZE; j++ {
if grid[i+offsetRow][j+offsetCol] == n {
return false
}
}
}

return true
}

func findNextEmptyCell(grid [][]int) (int, int, bool) {
for i:=0; i<BOARD_SIZE; i++ {
for j:=0; j<BOARD_SIZE; j++ {
if grid[i][j] == 0{
return i, j, true
}
}
}
return -1, -1, false
}


func isSolved(grid [][]int) bool {
row, col, found := findNextEmptyCell(grid)
if !found {
return true
}

// try numbers from 1 - BOARD_SIZE and back track if bad choices have been made
for n := 1; n <= BOARD_SIZE; n++ {
if isPossible(grid, row, col, n) {
grid[row][col] = n
if isSolved(grid) {
return true
}
grid[row][col] = 0
}
}
return false
}


func SolveSudoku(grid[][]int) [][]int {
// Assuming that we always get a valid sudoku board
isSolved(grid)
return grid
}
101 changes: 100 additions & 1 deletion sudoku_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,109 @@
package main
package sudoku

import (
"reflect"
"testing"
)


func TestIsPossible(t *testing.T) {
grid := [][]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},
}
result := isPossible(grid, 1, 1 , 1)
if result != false {
t.Errorf("Should not insert illegal number in grid. Expected:\n%v\n\nGot:\n%v", false, result)
}

result = isPossible(grid, 1, 1 , 4)
if result != true {
t.Errorf("Should be able to add legal number in the grid. Expected:\n%v\n\nGot:\n%v", true, result)
}
}

func TestIsSolved(t *testing.T) {
input := [][]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},
}

result := isSolved(input)

if result != true {
t.Errorf("Bad sudoku algorithm. Expected:\n%v\n\nGot:\n%v", true, result)
}

badInput := [][]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, 1},
{0, 0, 0, 0, 8, 0, 0, 7, 9},
}

result = isSolved(badInput)
if result != false {
t.Errorf("Bad sudoku board. Expected:\n%v\n\nGot:\n%v", false, result)
}
}

func TestFindNextEmptyCell(t *testing.T) {
input := [][]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},
}

i,j,found := findNextEmptyCell(input)

if i!=0 || j!=2 || found != true {
t.Errorf("Bad way to find next empty cell. \nExpected:\ni:%v, j:%v, found:%v \n\nGot:\ni:%v, j:%v, found:%v", 0, 2, true, i, j, found)
}

inputWithoutEmptyCells := [][]int{
{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},
}

i,j, found = findNextEmptyCell(inputWithoutEmptyCells)

if i!=-1 || j!=-1 || found !=false {
t.Errorf("Bad way to find next empty cell. \nExpected:\ni:%v, j:%v, found:%v \n\nGot:\ni:%v, j:%v, found:%v", -1, -1, false, i, j, found)
}
}

func TestSolveSudoku(t *testing.T) {
input := [][]int{
{5, 3, 0, 0, 7, 0, 0, 0, 0},
Expand Down
Loading