-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolver.java
129 lines (101 loc) · 2.99 KB
/
Solver.java
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import edu.princeton.cs.algs4.MinPQ;
public class Solver {
// find a solution to the initial board (using the A* algorithm)
private MyBoard initial;
private MyBoard twinInitial;
private MinPQ<MyBoard> minPQ;
private MinPQ<MyBoard> twinMinPQ;
private boolean solvable;
private List<Board> path;
public Solver(Board initial) {
if (initial == null)
throw new IllegalArgumentException();
this.initial = new MyBoard(initial, null);
this.twinInitial = new MyBoard(initial.twin(), null);
this.minPQ = new MinPQ<MyBoard>();
this.twinMinPQ = new MinPQ<MyBoard>();
this.path = new ArrayList<Board>();
this.solvable = false;
startSolving();
}
private class MyBoard implements Comparable<MyBoard>{
int moves = 0;
Board board;
int priority;
MyBoard previous;
public MyBoard(Board initial, MyBoard previous) {
board = initial;
if(previous != null) {
this.moves = previous.moves + 1;
}
this.previous = previous;
priority = board.manhattan() + moves;
}
@Override
public int compareTo(MyBoard o) {
if(this.priority< o.priority)
return -1;
if(this.priority == o.priority)
return 0;
return 1;
}
}
private void startSolving() {
minPQ.insert(initial);
twinMinPQ.insert(twinInitial);
while(!initial.board.isGoal() && !twinInitial.board.isGoal()) {
initial = minPQ.delMin();
twinInitial = twinMinPQ.delMin();
for(Board neighbor: initial.board.neighbors()) {
if(initial.previous == null || !neighbor.equals(initial.previous.board))
minPQ.insert(new MyBoard(neighbor, initial));
}
for(Board neighbor: twinInitial.board.neighbors()) {
if(twinInitial.previous == null || !neighbor.equals(twinInitial.previous.board))
twinMinPQ.insert(new MyBoard(neighbor, twinInitial));
}
}
if(initial.board.isGoal())
this.solvable = true;
}
// is the initial board solvable? (see below)
public boolean isSolvable() {
return solvable;
}
// min number of moves to solve initial board; -1 if unsolvable
public int moves() {
if (!isSolvable())
return -1;
return initial.moves;
}
// sequence of boards in a shortest solution; null if unsolvable
public Iterable<Board> solution() {
if(initial.board.isGoal()) {
path.clear();
path.add(initial.board);
return new PathIterator();
}
if (!isSolvable())
return null;
return new PathIterator();
}
private class PathIterator implements Iterable<Board>{
@Override
public Iterator<Board> iterator() {
MyBoard temp = new MyBoard(initial.board, initial.previous);
while(temp != null) {
path.add(temp.board);
temp = temp.previous;
}
Collections.reverse(path);
return path.iterator();
}
}
// test client (see below)
public static void main(String[] args) {
}
}