// generate a random 9x9 grid satisfying all the sudoku constraints. func generateFullGrid() board { // u is an unsolved puzzled with all 0s var u board // fill up the first row for i := 0; i < 9; i++ { u[i] = byte(i + 1) } // shuffle the first row for i := 0; i < 9; i++ { j := rand.Intn(i + 1) u[i], u[j] = u[j], u[i] } // solve the above using DLX in random mode to get random grid var solved board d := dlx.NewDLX(324) addRows(d, &u) d.Solve(1, true) sol := d.Solutions[0] for _, rID := range sol { r := rID / 81 c := (rID - r*81) / 9 n := rID - r*81 - c*9 solved[r*9+c] = byte(n + 1) } return solved }
// gets a random sudoku puzzle func randomPuzzle() *Sudoku { solved := generateFullGrid() // Pick a random permutation of the cells in the grid. toRemove := make([]int, 81) for i := 0; i < 81; i++ { toRemove[i] = i } for i := range toRemove { j := rand.Intn(i + 1) toRemove[i], toRemove[j] = toRemove[j], toRemove[i] } // Main idea to generate a puzzle with unique solution // For each cell in the permuted order: remove the number in that cell; // check to see if this has left the puzzle with multiple solutions; // if so, put the cell back. // "Binary search" method is faster by 3 times low, high := 0, 81 var unsolved board for { mid := (low + high) / 2 unsolved = solved if low == high { for _, cell := range toRemove[:mid-1] { unsolved[cell] = 0 } break } else { for _, cell := range toRemove[:mid] { unsolved[cell] = 0 } } d := dlx.NewDLX(324) addRows(d, &unsolved) d.Solve(2, false) if len(d.Solutions) != 1 { high = mid } else { low = mid + 1 } } return &Sudoku{puzzle: unsolved} }
// Solve searches for solution(s) of the puzzle using DLX. // Returns the number of the solutions found. Only the first solution is // saved. func (s *Sudoku) Solve(max int) int { d := dlx.NewDLX(324) // there are 324 constraints in a 9x9 puzzle addRows(d, &s.puzzle) // solve for 1 solution, pick the first column that has the least s // instead of any random column with the least s d.Solve(max, false) if len(d.Solutions) != 0 { sol := d.Solutions[0] for _, rID := range sol { r := rID / 81 c := (rID - r*81) / 9 n := rID - r*81 - c*9 s.solution[r*9+c] = byte(n + 1) } s.remaining = 0 } return len(d.Solutions) }