Example #1
0
// 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
}
Example #2
0
// 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}
}
Example #3
0
// 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)
}