-
Notifications
You must be signed in to change notification settings - Fork 0
/
Solver.java
147 lines (122 loc) · 4.68 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//package puzzle;
import java.util.Comparator;
//import edu.princeton.cs.introcs.In;
//import edu.princeton.cs.introcs.StdOut;
public class Solver {
private searchNode goal;
private searchNode goalTwin;
private class searchNode {
private Board board;
private int moves;
private searchNode preNode;
public searchNode(Board b, int moves, searchNode preNode) {
board = b;
this.moves = moves;
this.preNode = preNode;
}
}
public Solver(Board initial) { // find a solution to the initial board (using the A* algorithm)
searchNode minNode = null;
searchNode minNodeTwin = null;
priorityOrder po = new priorityOrder();
priorityOrder poTwin = new priorityOrder();
MinPQ<searchNode> pq = new MinPQ<searchNode>(po);
MinPQ<searchNode> pqTwin = new MinPQ<searchNode>(poTwin);
searchNode sn = new searchNode(initial,0,null);
searchNode snTwin = new searchNode(initial.twin(),0,null);
pq.insert(sn);
pqTwin.insert(snTwin);
//System.out.println(sn.board.toString());
minNode = (searchNode) pq.delMin();
minNodeTwin = (searchNode) pqTwin.delMin();
//System.out.println(i+":"+minNode.board.toString());
while (!minNode.board.isGoal() && !minNodeTwin.board.isGoal()) {
//System.out.println("======================");
for (Board b: minNode.board.neighbors()) {
if ((minNode.preNode == null) || (! b.equals(minNode.preNode.board))) {
//System.out.println("neighbor:"+b.toString()+"manhattan:"+b.manhattan()+" moves:"+(minNode.moves+1));
searchNode s = new searchNode(b, minNode.moves+1 ,minNode);
pq.insert(s);
//System.out.println("priority queue becomes:"+pq.size());
//System.out.println(" ");
}
}
minNode = (searchNode) pq.delMin();
//System.out.println("deleted min: when moves ="+minNode.moves+"\n"+minNode.board.toString());
for (Board b: minNodeTwin.board.neighbors()) {
if ((minNodeTwin.preNode == null) || (! b.equals(minNodeTwin.preNode.board))) {
searchNode s = new searchNode(b, minNodeTwin.moves+1 ,minNodeTwin);
pqTwin.insert(s);
}
}
minNodeTwin = (searchNode) pqTwin.delMin();
}
if (minNode.board.isGoal()) {
this.goal=minNode;
}
else {
this.goal=null;
}
if (minNodeTwin.board.isGoal()) {
this.goalTwin = minNodeTwin;
}
else {
this.goalTwin=null;
}
}
private class priorityOrder implements Comparator<searchNode> {
public int compare (searchNode s1, searchNode s2) {
int total1 = s1.board.manhattan()+s1.moves;
int total2 = s2.board.manhattan()+s2.moves;
if (total1>total2) return +1;
else if (total1<total2) return -1;
else return 0; }
}
public boolean isSolvable() { // is the initial board solvable?
if (goalTwin != null )
return false;
else return (goal!=null);
}
public int moves() { // min number of moves to solve initial board; -1 if no solution
if (this.isSolvable())
return goal.moves;
else
return -1;
}
public Iterable<Board> solution() { // sequence of boards in a shortest solution; null if no solution
if (this.isSolvable()) {
Stack <Board> boardSeq = new Stack<Board>();
boardSeq.push(goal.board);
searchNode nextNode = goal.preNode;
while (nextNode !=null) {
boardSeq.push(nextNode.board);
nextNode = nextNode.preNode;
}
return boardSeq;
}
else
return null;
}
public static void main(String[] args) // solve a slider puzzle (given below)
{
In in = new In("puzzle2x2-unsolvable1.txt");
int N = in.readInt();
int[][] tiles = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
tiles[i][j] = in.readInt();
}
}
Board initial = new Board(tiles);
Solver s = new Solver(initial);
if (s.isSolvable()) {
System.out.println("Solvable? "+s.isSolvable());
System.out.println("Minimum number of moves = "+s.moves());
for (Board one : s.solution()) {
System.out.println(one);
}
}
else
System.out.println("No solution possible");
}
}