Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
202
Task/Sudoku/Go/sudoku.go
Normal file
202
Task/Sudoku/Go/sudoku.go
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// sudoku puzzle representation is an 81 character string
|
||||
var puzzle = "" +
|
||||
"394 267 " +
|
||||
" 3 4 " +
|
||||
"5 69 2 " +
|
||||
" 45 9 " +
|
||||
"6 7" +
|
||||
" 7 58 " +
|
||||
" 1 67 8" +
|
||||
" 9 8 " +
|
||||
" 264 735"
|
||||
|
||||
func main() {
|
||||
printGrid("puzzle:", puzzle)
|
||||
if s := solve(puzzle); s == "" {
|
||||
fmt.Println("no solution")
|
||||
} else {
|
||||
printGrid("solved:", s)
|
||||
}
|
||||
}
|
||||
|
||||
// print grid (with title) from 81 character string
|
||||
func printGrid(title, s string) {
|
||||
fmt.Println(title)
|
||||
for r, i := 0, 0; r < 9; r, i = r+1, i+9 {
|
||||
fmt.Printf("%c %c %c | %c %c %c | %c %c %c\n", s[i], s[i+1], s[i+2],
|
||||
s[i+3], s[i+4], s[i+5], s[i+6], s[i+7], s[i+8])
|
||||
if r == 2 || r == 5 {
|
||||
fmt.Println("------+-------+------")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// solve puzzle in 81 character string format.
|
||||
// if solved, result is 81 character string.
|
||||
// if not solved, result is the empty string.
|
||||
func solve(u string) string {
|
||||
// construct an dlx object with 324 constraint columns.
|
||||
// other than the number 324, this is not specific to sudoku.
|
||||
d := newDlxObject(324)
|
||||
// now add constraints that define sudoku rules.
|
||||
for r, i := 0, 0; r < 9; r++ {
|
||||
for c := 0; c < 9; c, i = c+1, i+1 {
|
||||
b := r/3*3 + c/3
|
||||
n := int(u[i] - '1')
|
||||
if n >= 0 && n < 9 {
|
||||
d.addRow([]int{i, 81 + r*9 + n, 162 + c*9 + n,
|
||||
243 + b*9 + n})
|
||||
} else {
|
||||
for n = 0; n < 9; n++ {
|
||||
d.addRow([]int{i, 81 + r*9 + n, 162 + c*9 + n,
|
||||
243 + b*9 + n})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// run dlx. not sudoku specific.
|
||||
d.search()
|
||||
// extract the sudoku-specific 81 character result from the dlx solution.
|
||||
return d.text()
|
||||
}
|
||||
|
||||
// Knuth's data object
|
||||
type x struct {
|
||||
c *y
|
||||
u, d, l, r *x
|
||||
// except x0 is not Knuth's. it's pointer to first constraint in row,
|
||||
// so that the sudoku string can be constructed from the dlx solution.
|
||||
x0 *x
|
||||
}
|
||||
|
||||
// Knuth's column object
|
||||
type y struct {
|
||||
x
|
||||
s int // size
|
||||
n int // name
|
||||
}
|
||||
|
||||
// an object to hold the matrix and solution
|
||||
type dlx struct {
|
||||
ch []y // all column headers
|
||||
h *y // ch[0], the root node
|
||||
o []*x // solution
|
||||
}
|
||||
|
||||
// constructor creates the column headers but no rows.
|
||||
func newDlxObject(nCols int) *dlx {
|
||||
ch := make([]y, nCols+1)
|
||||
h := &ch[0]
|
||||
d := &dlx{ch, h, nil}
|
||||
h.c = h
|
||||
h.l = &ch[nCols].x
|
||||
ch[nCols].r = &h.x
|
||||
nh := ch[1:]
|
||||
for i := range ch[1:] {
|
||||
hi := &nh[i]
|
||||
ix := &hi.x
|
||||
hi.n = i
|
||||
hi.c = hi
|
||||
hi.u = ix
|
||||
hi.d = ix
|
||||
hi.l = &h.x
|
||||
h.r = ix
|
||||
h = hi
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// rows define constraints
|
||||
func (d *dlx) addRow(nr []int) {
|
||||
if len(nr) == 0 {
|
||||
return
|
||||
}
|
||||
r := make([]x, len(nr))
|
||||
x0 := &r[0]
|
||||
for x, j := range nr {
|
||||
ch := &d.ch[j+1]
|
||||
ch.s++
|
||||
np := &r[x]
|
||||
np.c = ch
|
||||
np.u = ch.u
|
||||
np.d = &ch.x
|
||||
np.l = &r[(x+len(r)-1)%len(r)]
|
||||
np.r = &r[(x+1)%len(r)]
|
||||
np.u.d, np.d.u, np.l.r, np.r.l = np, np, np, np
|
||||
np.x0 = x0
|
||||
}
|
||||
}
|
||||
|
||||
// extracts 81 character sudoku string
|
||||
func (d *dlx) text() string {
|
||||
b := make([]byte, len(d.o))
|
||||
for _, r := range d.o {
|
||||
x0 := r.x0
|
||||
b[x0.c.n] = byte(x0.r.c.n%9) + '1'
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// the dlx algorithm
|
||||
func (d *dlx) search() bool {
|
||||
h := d.h
|
||||
j := h.r.c
|
||||
if j == h {
|
||||
return true
|
||||
}
|
||||
c := j
|
||||
for minS := j.s; ; {
|
||||
j = j.r.c
|
||||
if j == h {
|
||||
break
|
||||
}
|
||||
if j.s < minS {
|
||||
c, minS = j, j.s
|
||||
}
|
||||
}
|
||||
|
||||
cover(c)
|
||||
k := len(d.o)
|
||||
d.o = append(d.o, nil)
|
||||
for r := c.d; r != &c.x; r = r.d {
|
||||
d.o[k] = r
|
||||
for j := r.r; j != r; j = j.r {
|
||||
cover(j.c)
|
||||
}
|
||||
if d.search() {
|
||||
return true
|
||||
}
|
||||
r = d.o[k]
|
||||
c = r.c
|
||||
for j := r.l; j != r; j = j.l {
|
||||
uncover(j.c)
|
||||
}
|
||||
}
|
||||
d.o = d.o[:len(d.o)-1]
|
||||
uncover(c)
|
||||
return false
|
||||
}
|
||||
|
||||
func cover(c *y) {
|
||||
c.r.l, c.l.r = c.l, c.r
|
||||
for i := c.d; i != &c.x; i = i.d {
|
||||
for j := i.r; j != i; j = j.r {
|
||||
j.d.u, j.u.d = j.u, j.d
|
||||
j.c.s--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func uncover(c *y) {
|
||||
for i := c.u; i != &c.x; i = i.u {
|
||||
for j := i.l; j != i; j = j.l {
|
||||
j.c.s++
|
||||
j.d.u, j.u.d = j, j
|
||||
}
|
||||
}
|
||||
c.r.l, c.l.r = &c.x, &c.x
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue