Repository navigation
Expand file tree
/
Copy pathsolver.go
More file actions
111 lines (104 loc) · 2.3 KB
/
Copy pathsolver.go
File metadata and controls
111 lines (104 loc) · 2.3 KB
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package main
import "fmt"
type Node struct {
cube Cube
prev_state *Node
last_turn Move
depth uint
}
func newNode(c Cube) Node {
return Node{cube: c, prev_state: nil, last_turn: NO_MOVE, depth: 0}
}
func (n *Node) get_children() []Node {
// Check if its the root node
var nodes []Node
if n.last_turn == NO_MOVE {
nodes = make([]Node, 18)
for x := range 18 {
move := Move(x)
c := n.cube
c.move(move)
nodes[x] = Node{cube: c, prev_state: n, last_turn: move, depth: n.depth + 1}
}
} else {
v := int(n.last_turn) / 3
// Check if its in the first half
if v < 3 {
nodes = make([]Node, 12)
i := 0
for x := range 18 {
// Disallow turns on opposite side
if (x/3 != v) && (x/3 != v+3) {
move := Move(x)
c := n.cube
c.move(move)
nodes[i] = Node{cube: c, prev_state: n, last_turn: move, depth: n.depth + 1}
i++
}
}
} else {
nodes = make([]Node, 15)
i := 0
for x := range 18 {
if x/3 != v {
move := Move(x)
c := n.cube
c.move(move)
nodes[i] = Node{cube: c, prev_state: n, last_turn: move, depth: n.depth + 1}
i++
}
}
}
}
return nodes
}
func (n *Node) bfs() []Move {
target_state := newCube()
queue := []Node{*n}
for {
node := queue[0]
if node.cube == target_state {
// We did it!
sol := []Move{}
for node.prev_state != nil {
sol = append([]Move{node.last_turn}, sol...)
node = *node.prev_state
}
return sol
}
queue = append(queue[1:], node.get_children()...)
}
}
func (n *Node) IDA() []Move {
target_state := newCube()
// Do Depth first search with max depth and heuristic
for max_depth := range uint(20) {
fmt.Println("Current depth:", max_depth)
node := n.IDA_rec(&target_state, max_depth)
if node != nil {
// Solution found!
sol := []Move{}
for node.prev_state != nil {
sol = append([]Move{node.last_turn}, sol...)
node = node.prev_state
}
return sol
}
}
return nil
}
func (n *Node) IDA_rec(target *Cube, max_depth uint) *Node {
heuristic := n.cube.getHeuristic()
if max_depth < n.depth+uint(heuristic) {
return nil
} else if heuristic == 0 {
return n
}
for _, child := range n.get_children() {
potential_solution := child.IDA_rec(target, max_depth)
if potential_solution != nil {
return potential_solution
}
}
return nil
}