Skip to content

Commit 93a47e7

Browse files
committed
Improved solution
1 parent e4ccc2d commit 93a47e7

File tree

2 files changed

+151
-11
lines changed

2 files changed

+151
-11
lines changed

week4/priority-queues/assignment-8-puzzle/Board.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import java.util.ArrayList;
2+
13
public class Board {
24
private int n;
35
private int[][] tiles;
@@ -15,7 +17,7 @@ public Board(int[][] tiles) {
1517

1618
// string representation of this board
1719
public String toString() {
18-
String s = new String();
20+
String s = "";
1921

2022
s = s.concat(dimension() + "\n");
2123

@@ -56,8 +58,8 @@ public int manhattan() {
5658
int x = (v - 1) / n;
5759
int y = (v - 1) % n;
5860

59-
int xd = Math.abs(x - j);
60-
int xy = Math.abs(y - i);
61+
int xd = Math.abs(x - i);
62+
int xy = Math.abs(y - j);
6163

6264
cnt += xd + xy;
6365
}
@@ -83,6 +85,8 @@ public boolean equals(Object y) {
8385

8486
Board other = (Board) y;
8587
if (dimension() != other.dimension()) return false;
88+
if (hamming() != other.hamming()) return false;
89+
if (manhattan() != other.manhattan()) return false;
8690

8791
return true;
8892

@@ -97,12 +101,34 @@ public boolean equals(Object y) {
97101

98102
// all neighboring boards
99103
public Iterable<Board> neighbors() {
100-
return null;
104+
int emptyX = -1;
105+
int emptyY = -1;
106+
for (int i = 0; i < dimension(); ++i)
107+
for (int j = 0; j < dimension(); ++j) {
108+
if (tiles[i][j] == 0) {
109+
emptyX = i;
110+
emptyY = j;
111+
break;
112+
}
113+
}
114+
115+
ArrayList<Board> neighbors = new ArrayList<Board>();
116+
if (emptyX > 0) neighbors.add(neighbour(emptyX, emptyY, -1, 0));
117+
if (emptyX < 2) neighbors.add(neighbour(emptyX, emptyY, 1, 0));
118+
if (emptyY > 0) neighbors.add(neighbour(emptyX, emptyY, 0, -1));
119+
if (emptyY < 2) neighbors.add(neighbour(emptyX, emptyY, 0, 1));
120+
return neighbors;
101121
}
102122

103123
// a board that is obtained by exchanging any pair of tiles
104124
public Board twin() {
105-
return null;
125+
Board twinBoard = new Board(tiles);
126+
127+
if (tiles[0][0] == 0) twinBoard.swap(0, 1, 1, 1);
128+
else if (tiles[0][1] == 0) twinBoard.swap(0, 0, 1, 0);
129+
else twinBoard.swap(0, 0, 0, 1);
130+
131+
return twinBoard;
106132
}
107133

108134
// unit testing (not graded)
@@ -113,4 +139,17 @@ public static void main(String[] args) {
113139
private int goalAt(int i, int j) {
114140
return i * n + j + 1;
115141
}
142+
143+
private Board neighbour(int x, int y, int dx, int dy) {
144+
swap(x, y, x + dx, y + dy);
145+
Board board = new Board(tiles);
146+
swap(x, y, x + dx, y + dy);
147+
return board;
148+
}
149+
150+
private void swap(int i, int j, int x, int y) {
151+
int tmp = tiles[i][j];
152+
tiles[i][j] = tiles[y][x];
153+
tiles[x][y] = tmp;
154+
}
116155
}

week4/priority-queues/assignment-8-puzzle/Solver.java

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,131 @@
1+
import java.util.Comparator;
2+
13
import edu.princeton.cs.algs4.In;
24
import edu.princeton.cs.algs4.StdOut;
5+
import edu.princeton.cs.algs4.Stack;
6+
import edu.princeton.cs.algs4.MinPQ;
37

48
public class Solver {
9+
private Board initial;
10+
private int moves;
11+
private boolean solvable;
12+
private Stack<Board> solution;
13+
14+
// search node
15+
private static class Node {
16+
Board board;
17+
int moves;
18+
int priority;
19+
Node prev;
20+
}
21+
522
// find a solution to the initial board (using the A* algorithm)
623
public Solver(Board initial) {
724
if (initial == null) {
825
throw new IllegalArgumentException("initial argument to Solver constructor is null");
926
}
27+
this.initial = initial;
28+
solve();
1029
}
1130

1231
// is the initial board solvable? (see below)
1332
public boolean isSolvable() {
14-
return false;
33+
return this.solvable;
1534
}
1635

1736
// min number of moves to solve initial board; -1 if unsolvable
1837
public int moves() {
19-
// Return -1 in moves() if the board is unsolvable.
20-
return -1;
38+
return this.moves;
2139
}
2240

2341
// sequence of boards in a shortest solution; null if unsolvable
2442
public Iterable<Board> solution() {
25-
// Return null in solution() if the board is unsolvable.
26-
return null;
43+
return this.solution;
44+
}
45+
46+
private void solve() {
47+
this.moves = -1;
48+
this.solvable = true;
49+
this.solution = new Stack<Board>();
50+
51+
MinPQ<Node> pq = initPQ(initial);
52+
MinPQ<Node> twinpq = initPQ(initial.twin());
53+
54+
while (true) {
55+
Node searchNode = pq.delMin();
56+
Node prevNode = searchNode.prev;
57+
Board searchBoard = searchNode.board;
58+
59+
if (searchBoard.isGoal()) {
60+
this.solvable = true;
61+
this.moves = searchNode.moves;
62+
this.solution = findPath(searchNode);
63+
break;
64+
}
65+
66+
for (Board b : searchBoard.neighbors()) {
67+
if (prevNode == null || !prevNode.board.equals(b)) {
68+
Node temp = new Node();
69+
temp.prev = searchNode;
70+
temp.board = b;
71+
temp.moves = searchNode.moves + 1;
72+
temp.priority = temp.moves + b.manhattan();
73+
pq.insert(temp);
74+
}
75+
}
76+
77+
Node twinSearchNode = twinpq.delMin();
78+
Node twinPrevNode = twinSearchNode.prev;
79+
Board twinSearchBoard = twinSearchNode.board;
80+
81+
if (twinSearchBoard.isGoal()) {
82+
this.solvable = false;
83+
break;
84+
}
85+
86+
for (Board b : twinSearchBoard.neighbors()) {
87+
if (twinPrevNode == null || twinPrevNode.board.equals(b)) {
88+
Node temp = new Node();
89+
temp.prev = twinSearchNode;
90+
temp.board = b;
91+
temp.moves = twinSearchNode.moves + 1;
92+
temp.priority = temp.moves + b.manhattan();
93+
twinpq.insert(temp);
94+
}
95+
}
96+
}
97+
}
98+
99+
private Comparator<Node> priority() {
100+
return new ByPriority();
101+
}
102+
103+
private class ByPriority implements Comparator<Node> {
104+
public int compare(Node n1, Node n2) {
105+
return n1.priority > n2.priority ? 1 : n1.priority < n2.priority ? -1 : 0;
106+
}
107+
}
108+
109+
private MinPQ<Node> initPQ(Board root) {
110+
Node rootNode = new Node();
111+
rootNode.board = root;
112+
rootNode.moves = 0;
113+
rootNode.priority = root.manhattan();
114+
rootNode.prev = null;
115+
116+
MinPQ<Node> pq = new MinPQ<Node>(priority());
117+
pq.insert(rootNode);
118+
return pq;
119+
}
120+
121+
private Stack<Board> findPath(Node leaf) {
122+
Stack<Board> path = new Stack<Board>();
123+
Node temp = leaf;
124+
while (temp != null) {
125+
path.push(temp.board);
126+
temp = temp.prev;
127+
}
128+
return path;
27129
}
28130

29131
// test client (see below)
@@ -53,5 +155,4 @@ public static void main(String[] args) {
53155
}
54156
}
55157
}
56-
57158
}

0 commit comments

Comments
 (0)