Refactor Sudoku field and solver implementation
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package strategies
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.kleiax.de/homepage/field"
|
||||
)
|
||||
|
||||
const solvedGrid = "123456789456789123789123456234567891567891234891234567345678912678912345912345678"
|
||||
|
||||
func strategyField(t *testing.T, digits string) *field.Field {
|
||||
t.Helper()
|
||||
props := field.Properties{Rows: 9, Columns: 9, BlockRows: 3, BlockColumns: 3, BlockSizeRow: 3, BlockSizeColumn: 3}
|
||||
cells := make([][]field.Cell, 9)
|
||||
for row := range cells {
|
||||
cells[row] = make([]field.Cell, 9)
|
||||
for column := range cells[row] {
|
||||
pos := field.NewPosition(row, column, row/3, column/3, row%3, column%3)
|
||||
cells[row][column] = *field.NewCell(int(digits[row*9+column]-'0'), pos)
|
||||
}
|
||||
}
|
||||
result, err := field.New(props, cells)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func TestLastDigitDeduplicatesOverlappingParts(t *testing.T) {
|
||||
f := strategyField(t, "0"+solvedGrid[1:])
|
||||
strategy := &LastDigit{}
|
||||
strategy.Init(f)
|
||||
if got := strategy.SearchProgressableCells(); got != 1 {
|
||||
t.Fatalf("SearchProgressableCells() = %d, want 1", got)
|
||||
}
|
||||
changes, err := strategy.ApplyAll()
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyAll() error = %v", err)
|
||||
}
|
||||
if len(changes) != 1 || !f.IsSolved() {
|
||||
t.Fatalf("changes = %d, solved = %v", len(changes), f.IsSolved())
|
||||
}
|
||||
}
|
||||
|
||||
func TestHiddenSingleUsesCandidateValuesNotSliceIndexes(t *testing.T) {
|
||||
f := strategyField(t, strings.Repeat("0", 81))
|
||||
first, _ := f.GetCell(0, 0)
|
||||
second, _ := f.GetCell(0, 1)
|
||||
third, _ := f.GetCell(0, 2)
|
||||
for _, setup := range []struct {
|
||||
cell *field.Cell
|
||||
note int
|
||||
}{{first, 9}, {second, 8}, {third, 8}} {
|
||||
if err := setup.cell.GetNotes().Add(f, setup.cell, setup.note, "test", nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
strategy := &HiddenSingle{}
|
||||
strategy.Init(f)
|
||||
strategy.SearchProgressableCells()
|
||||
found := false
|
||||
for _, change := range strategy.changes {
|
||||
if change.Cell == first && change.Value == 9 {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("hidden single for candidate value 9 was not found")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersection3IsSorted(t *testing.T) {
|
||||
got := intersection3([]int{9, 1, 5}, []int{5, 9, 1}, []int{9, 5, 1})
|
||||
want := []int{1, 5, 9}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Fatalf("intersection3() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user