func BenchmarkBacktrack2(b *testing.B) { board, err := puzzle.New([]byte(testInput2)) if err != nil { log.Fatalln(err) } benchmarkBacktrack(board, b) }
func BenchmarkDLX5(b *testing.B) { board, err := puzzle.New([]byte(testInput5)) if err != nil { log.Fatalln(err) } benchmarkDLX(board, b) }
func TestCoverEmptyBoard(t *testing.T) { board, err := puzzle.New([]byte(emptyBoard)) assert.NotNil(t, board) assert.NoError(t, err) baseCover := baseCover() cover := exactCover(board) // Since we haven't introduced any new constraints (empty board) except for // the basic ones the exact cover should equal the base cover for i := range baseCover { for j := range baseCover[i] { assert.Equal(t, cover[i][j], baseCover[i][j]) } } }
func TestSolvers(t *testing.T) { var tests = []struct { input string shouldSolve bool }{ {testInput1, true}, {testInput2, true}, {testInput3, false}, {testInput4, true}, {testInput5, true}, } for _, test := range tests { b, err := puzzle.New([]byte(test.input)) assert.NoError(t, err) assert.NotNil(t, b) for _, solver := range buildSolvers(b) { solvedBoard := solver.Solve() assert.Equal(t, test.shouldSolve, solvedBoard.Solved()) } } }
func TestCoverSolvedBoard(t *testing.T) { board, err := puzzle.New([]byte(solvedBoard)) assert.NotNil(t, board) assert.NoError(t, err) cover := exactCover(board) // For each cell = N (N in [1,9]) all arrays in the cover matrix at the cells // row/col should be all zeroes except for the Nth array. for i := 0; i < size; i++ { for j := 0; j < size; j++ { n := board.ValueAt(i, j) for num := 0; num < size; num++ { if num != n-1 { arr := cover[index(i, j, num)] for _, v := range arr { assert.Equal(t, 0, v) } } } } } }
func main() { flag.StringVar( &generateFlag, "generate", "", "Generate a Sudoku board, accepts inputs: 'easy', 'medium' 'hard'", ) flag.BoolVar( &printDifficuly, "print-difficulty", false, "Prints the difficulty of the input board", ) flag.Parse() // Generate a Sudoku board and print it to stdout if len(generateFlag) > 0 { for { // generate a random board board, err := puzzle.Generate(generateFlag) if err != nil { log.Fatalln(err) } // make sure it can be solved // the backtrack algorithm is used to solve the board since it's // faster (in most cases) than DLX to detect unsolvable boards solvedBoard := backtrack.NewSolver(board).Solve() if solvedBoard.Solved() { fmt.Println(strings.Replace(board.String(), "0", "_", -1)) return } } } // Read Sudoku board from stdin b, err := ioutil.ReadAll(bufio.NewReader(os.Stdin)) if err != nil { log.Fatalln(err) } // Build the board board, err := puzzle.New(b) if err != nil { log.Fatalln(err) } // Just print the difficulty of the board if the caller asks for it if printDifficuly { fmt.Println(board.Difficulty()) return } // Solve the board dlx := dlx.NewSolver(board) solvedBoard := dlx.Solve() if !solvedBoard.Solved() { log.Fatalln(errUnsolvable) } fmt.Println(solvedBoard) }