-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolver.go
74 lines (68 loc) · 1.49 KB
/
solver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package fm3
import (
"errors"
"fmt"
)
type Solver struct {
saw map[int64]bool // hash values of seen circums. TODO: Use Circum struct as the key to avoid possible hash collision.
debug bool
}
func NewSolver() *Solver {
return &Solver{
saw: make(map[int64]bool),
}
}
type Prob struct {
board *Circum
step int
}
// solve returns if there is at least one solution.
// returns error too if there is more than one solutions.
func (s *Solver) Solve(prob *Prob) (bool, error) {
return s.solve(prob.board, prob.step)
}
func (s *Solver) solve(prob *Circum, step int) (bool, error) {
if s.debug {
fmt.Printf("Solving\n%d手\n%s", step, prob)
}
if !prob.Hither {
return false, errors.New("turn must be hither.")
}
if step%2 != 1 {
return false, errors.New("step must be odd.")
}
var q []*Circum
q = append(q, prob)
for i := 0; i < step; i++ {
if s.debug {
fmt.Printf("step %d: #states: %d\n", i, len(q))
}
var nq []*Circum
for _, c := range q {
if !c.Hither && c.Mated() {
return true, nil // early mate. TODO: return some error
}
for _, nc := range c.Nexts() {
// TODO: Good branch cut option like FM's -m option.
if !s.saw[nc.hash()] {
nq = append(nq, nc)
s.saw[nc.hash()] = true
}
}
}
q = nq
}
found := false
for _, c := range q {
if !c.Hither && c.Mated() {
if s.debug {
fmt.Printf("Step: %d\n%s\n", step, c)
}
if found {
return true, errors.New("More than one solution.")
}
found = true
}
}
return found, nil
}