|
@@ -1,57 +1,101 @@
|
|
|
package main
|
|
|
|
|
|
-// IntMap ...
|
|
|
-type IntMap []int
|
|
|
+// Slice ...
|
|
|
+type Slice []interface{}
|
|
|
|
|
|
-func (im IntMap) set(id, num int) {
|
|
|
- im[id] |= 1 << uint(num)
|
|
|
+// Pop ...
|
|
|
+func (s *Slice) Pop() interface{} {
|
|
|
+ l := len(*s)
|
|
|
+ top := (*s)[l-1]
|
|
|
+ *s = (*s)[:l-1]
|
|
|
+ return top
|
|
|
}
|
|
|
|
|
|
-func (im IntMap) get(id, num int) bool {
|
|
|
- return im[id]&(1<<uint(num)) == 1
|
|
|
+// Empty ...
|
|
|
+func (s Slice) Empty() bool {
|
|
|
+ return len(s) == 0
|
|
|
}
|
|
|
|
|
|
-func getAnswer(occur int) (ans byte, ok bool) {
|
|
|
- cnt := 0
|
|
|
- for i, bit := 1, 1; i <= 9; i++ {
|
|
|
- if occur&bit == 0 {
|
|
|
- cnt++
|
|
|
- ans = byte(i + '0')
|
|
|
- }
|
|
|
- bit <<= 1
|
|
|
+// Grid ...
|
|
|
+type Grid struct {
|
|
|
+ X int
|
|
|
+ Y int
|
|
|
+ Val int
|
|
|
+}
|
|
|
+
|
|
|
+// SudokuMap ...
|
|
|
+type SudokuMap [][]int
|
|
|
+
|
|
|
+// NewSudokuMap ...
|
|
|
+func NewSudokuMap() (m SudokuMap) {
|
|
|
+ m = make([][]int, 3) // 0 for col, 1 for row and 2 for block id
|
|
|
+ for i := range m {
|
|
|
+ m[i] = make([]int, 9)
|
|
|
}
|
|
|
- return ans, cnt == 1
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+var mask = [...]int{1, 2, 4, 8, 16, 32, 64, 128, 256, 512}
|
|
|
+
|
|
|
+// Put ...
|
|
|
+func (m SudokuMap) Put(x, y, val int) {
|
|
|
+ m[0][x] |= mask[val]
|
|
|
+ m[1][y] |= mask[val]
|
|
|
+ m[2][y/3*3+x/3] |= mask[val]
|
|
|
+}
|
|
|
+
|
|
|
+// Get ...
|
|
|
+func (m SudokuMap) Get(x, y, val int) bool {
|
|
|
+ return (m[0][x]|m[1][y]|m[2][y/3*3+x/3])&mask[val] != 0
|
|
|
+}
|
|
|
+
|
|
|
+// Del ...
|
|
|
+func (m SudokuMap) Del(x, y, val int) {
|
|
|
+ mask := mask[val] ^ 0x3FF
|
|
|
+ m[0][x] &= mask
|
|
|
+ m[1][y] &= mask
|
|
|
+ m[2][y/3*3+x/3] &= mask
|
|
|
}
|
|
|
|
|
|
func solveSudoku(board [][]byte) {
|
|
|
- var rowMap, colMap, blockMap IntMap
|
|
|
- rowMap = make([]int, 9)
|
|
|
- colMap = make([]int, 9)
|
|
|
- blockMap = make([]int, 9)
|
|
|
- for y, row := range board {
|
|
|
- for x, col := range row {
|
|
|
- if col == '.' {
|
|
|
- continue
|
|
|
+ // Init sudoku and count blank grid
|
|
|
+ m := NewSudokuMap()
|
|
|
+ blank := 0
|
|
|
+ for y := range board {
|
|
|
+ for x := range board[y] {
|
|
|
+ if board[y][x] == '.' {
|
|
|
+ blank++
|
|
|
+ } else {
|
|
|
+ m.Put(x, y, int(board[y][x]-'0'))
|
|
|
}
|
|
|
- num := int(col - '0')
|
|
|
- rowMap.set(y, num)
|
|
|
- colMap.set(x, num)
|
|
|
- blockMap.set(y/3*3+x/3, num)
|
|
|
}
|
|
|
}
|
|
|
- for y, row := range board {
|
|
|
- for x, col := range row {
|
|
|
- if col != '.' {
|
|
|
- continue
|
|
|
- }
|
|
|
- blockID := y/3*3 + x/3
|
|
|
- occur := rowMap[y] & colMap[x] & blockMap[blockID]
|
|
|
- ans, ok := getAnswer(occur)
|
|
|
- if ok {
|
|
|
- board[y][x] = ans
|
|
|
+ var stack Slice = make([]interface{}, 0)
|
|
|
+ for len(stack) != blank { // Assume that all quetion is solvable
|
|
|
+ for y := 0; y < 9; y++ {
|
|
|
+ for x, i := 0, 1; x < 9; x++ {
|
|
|
+ if board[y][x] == '.' { // Never use 'copy' or 'range' when backtracking in golang!!!
|
|
|
+ for ; i <= 9; i++ {
|
|
|
+ if !m.Get(x, y, i) { // Is valid
|
|
|
+ m.Put(x, y, i)
|
|
|
+ stack = append(stack, Grid{x, y, i})
|
|
|
+ i = 1 // Reset next val
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if i == 10 { // Not valid
|
|
|
+ top := stack.Pop().(Grid)
|
|
|
+ m.Del(top.X, top.Y, top.Val)
|
|
|
+ x, y, i = top.X-1, top.Y, top.Val+1 // Try next val of last step
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ for !stack.Empty() {
|
|
|
+ top := stack.Pop().(Grid)
|
|
|
+ board[top.Y][top.X] = byte(top.Val + '0')
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func main() {
|
|
@@ -67,4 +111,18 @@ func main() {
|
|
|
{'.', '.', '.', '.', '8', '.', '.', '7', '9'}}
|
|
|
solveSudoku(b1)
|
|
|
printBoard(b1)
|
|
|
+
|
|
|
+ println()
|
|
|
+ b2 := [][]byte{
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'},
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'},
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'},
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'},
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'},
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'},
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'},
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'},
|
|
|
+ {'.', '.', '.', '.', '.', '.', '.', '.', '.'}}
|
|
|
+ solveSudoku(b2)
|
|
|
+ printBoard(b2)
|
|
|
}
|