Created
March 8, 2017 08:20
-
-
Save chheller/73755e1ceec2910e08bedbf5344b02ef to your computer and use it in GitHub Desktop.
An implementation of BFS to solve a classic sliding puzzle problem.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Comparator; | |
import java.util.LinkedList; | |
import java.util.Queue; | |
import java.util.TreeSet; | |
class StateComparator implements Comparator<State> { | |
public int compare(State a, State b) { | |
for (int i = 0; i < 22; i++) { | |
if (a.state[i] < b.state[i]) | |
return -1; | |
else if (a.state[i] > b.state[i]) | |
return 1; | |
} | |
return 0; | |
} | |
} | |
public class Driver { | |
public static boolean[][] map; | |
public static int[][] shapes = { { 1, 3, 2, 3, 1, 4, 2, 4 }, { 1, 5, 1, 6, 2, 6 }, { 2, 5, 3, 5, 3, 6 }, | |
{ 3, 7, 3, 8, 4, 8 }, { 4, 7, 5, 7, 5, 8 }, { 6, 7, 7, 7, 6, 8 }, { 5, 4, 5, 5, 5, 6, 4, 5 }, | |
{ 6, 4, 6, 5, 6, 6, 7, 5 }, { 8, 5, 8, 6, 7, 6 }, { 6, 2, 6, 3, 5, 3 }, { 5, 1, 6, 1, 5, 2 } }; | |
private static Viz viz; | |
public static LinkedList<State> BFS() { | |
StateComparator comp = new StateComparator(); | |
TreeSet<State> set = new TreeSet<State>(comp); | |
// HashSet<byte[]> set = new HashSet<byte[]>(); | |
Queue<State> queue = new LinkedList<State>(); | |
LinkedList<State> path = new LinkedList<State>(); | |
State root = new State(null); | |
queue.add(root); | |
set.add(root); | |
while (!queue.isEmpty()) { | |
// if (queue.size() % 10000 == 0) | |
// System.out.println(queue.size()); | |
State state = queue.remove(); | |
viz.view.draw(state.state); | |
if (state.state[0] == 4 && state.state[1] == -2) { | |
while (state.parent != null) { | |
path.add(state); | |
state = state.parent; | |
} | |
return path; | |
} | |
ArrayList<State> frontier_states = Search_Frontier(state.state); | |
for (State frontier_state : frontier_states) { | |
if (!set.contains(frontier_state)) { | |
State newState = new State(state, frontier_state.state); | |
queue.add(newState); | |
set.add(newState); | |
} | |
} | |
} | |
return null; | |
} | |
private static ArrayList<State> Search_Frontier(byte[] state) { | |
//TODO Find the frontier | |
ArrayList<State> return_states = new ArrayList<State>(); | |
byte[][] possible_states = new byte[44][22]; | |
for (int i = 0; i < 11; i++) { | |
byte[] possible_state_up = Arrays.copyOf(state, state.length); | |
byte[] possible_state_down = Arrays.copyOf(state, state.length); | |
byte[] possible_state_left = Arrays.copyOf(state, state.length); | |
byte[] possible_state_right = Arrays.copyOf(state, state.length); | |
possible_state_up[i * 2 + 1] = (byte) (possible_state_up[i * 2 + 1] - 1); | |
possible_states[i * 4] = Arrays.copyOf(possible_state_up, possible_state_up.length); | |
possible_state_down[i * 2 + 1] = (byte) (possible_state_down[i * 2 + 1] + 1); | |
possible_states[i * 4 + 1] = Arrays.copyOf(possible_state_down, possible_state_down.length); | |
possible_state_left[i * 2] = (byte) (possible_state_left[i * 2] - 1); | |
possible_states[i * 4 + 2] = Arrays.copyOf(possible_state_left, possible_state_left.length); | |
possible_state_right[i * 2] = (byte) (possible_state_right[i * 2] + 1); | |
possible_states[i * 4 + 3] = Arrays.copyOf(possible_state_right, possible_state_right.length); | |
} | |
/* byte[][] possible_states = {{0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, | |
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0} , | |
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}}; | |
ArrayList<State> return_states = new ArrayList<State>(); | |
*/ | |
for (int i = 0; i < 44; i++) { | |
if (canDraw(possible_states[i])) | |
return_states.add(new State(null, possible_states[i])); | |
} | |
return return_states; | |
} | |
private static boolean canDraw(byte[] state) { | |
initMap(); | |
if (!drawPiece(state[0] + shapes[0][0], state[1] + shapes[0][1], state[0] + shapes[0][2], | |
state[1] + shapes[0][3], state[0] + shapes[0][4], state[1] + shapes[0][5], state[0] + shapes[0][6], | |
state[1] + shapes[0][7])) | |
return false; | |
if (!drawPiece(state[2] + shapes[1][0], state[3] + shapes[1][1], state[2] + shapes[1][2], | |
state[3] + shapes[1][3], state[2] + shapes[1][4], state[3] + shapes[1][5])) | |
return false; | |
if (!drawPiece(state[4] + shapes[2][0], state[5] + shapes[2][1], state[4] + shapes[2][2], | |
state[5] + shapes[2][3], state[4] + shapes[2][4], state[5] + shapes[2][5])) | |
return false; | |
if (!drawPiece(state[6] + shapes[3][0], state[7] + shapes[3][1], state[6] + shapes[3][2], | |
state[7] + shapes[3][3], state[6] + shapes[3][4], state[7] + shapes[3][5])) | |
return false; | |
if (!drawPiece(state[8] + shapes[4][0], state[9] + shapes[4][1], state[8] + shapes[4][2], | |
state[9] + shapes[4][3], state[8] + shapes[4][4], state[9] + shapes[4][5])) | |
return false; | |
if (!drawPiece(state[10] + shapes[5][0], state[11] + shapes[5][1], state[10] + shapes[5][2], | |
state[11] + shapes[5][3], state[10] + shapes[5][4], state[11] + shapes[5][5])) | |
return false; | |
if (!drawPiece(state[12] + shapes[6][0], state[13] + shapes[6][1], state[12] + shapes[6][2], | |
state[13] + shapes[6][3], state[12] + shapes[6][4], state[13] + shapes[6][5], state[12] + shapes[6][6], | |
state[13] + shapes[6][7])) | |
return false; | |
if (!drawPiece(state[14] + shapes[7][0], state[15] + shapes[7][1], state[14] + shapes[7][2], | |
state[15] + shapes[7][3], state[14] + shapes[7][4], state[15] + shapes[7][5], state[14] + shapes[7][6], | |
state[15] + shapes[7][7])) | |
return false; | |
if (!drawPiece(state[16] + shapes[8][0], state[17] + shapes[8][1], state[16] + shapes[8][2], | |
state[17] + shapes[8][3], state[16] + shapes[8][4], state[17] + shapes[8][5])) | |
return false; | |
if (!drawPiece(state[18] + shapes[9][0], state[19] + shapes[9][1], state[18] + shapes[9][2], | |
state[19] + shapes[9][3], state[18] + shapes[9][4], state[19] + shapes[9][5])) | |
return false; | |
if (!drawPiece(state[20] + shapes[10][0], state[21] + shapes[10][1], state[20] + shapes[10][2], | |
state[21] + shapes[10][3], state[20] + shapes[10][4], state[21] + shapes[10][5])) | |
return false; | |
return true; | |
} | |
private static boolean drawPiece(int x1, int y1, int x2, int y2, int x3, int y3) { | |
if (map[y1][x1]) | |
map[y1][x1] = false; | |
else | |
return false; | |
if (map[y2][x2]) | |
map[y2][x2] = false; | |
else | |
return false; | |
if (map[y3][x3]) | |
map[y3][x3] = false; | |
else | |
return false; | |
return true; | |
} | |
private static boolean drawPiece(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) { | |
if (map[y1][x1]) | |
map[y1][x1] = false; | |
else | |
return false; | |
if (map[y2][x2]) | |
map[y2][x2] = false; | |
else | |
return false; | |
if (map[y3][x3]) | |
map[y3][x3] = false; | |
else | |
return false; | |
if (map[y4][x4]) | |
map[y4][x4] = false; | |
else | |
return false; | |
return true; | |
} | |
/* | |
* private static boolean canDraw(byte[] state) { | |
* | |
* boolean[][] scope_map = new boolean[10][10]; for (int i = 0; i < 10; i++) | |
* { scope_map[i] = Arrays.copyOf(map[i], map[i].length); } | |
* | |
* for (int i = 0; i < 11; i++) { | |
* | |
* for (int j = 0; j < shapes[i].length / 2; j++) { | |
* | |
* int mapx = state[i * 2] + shapes[i][j * 2 + 1]; int mapy = state[i * 2 + | |
* 1] + shapes[i][j * 2 + 2]; // System.out.println(String.format("Id %1$d | |
* Shape (%2$d,%3$d) // Map (%4$d,%5$d)\nState %6$s",i, shapes[i][j * 2 + // | |
* 1],shapes[i][j * 2 + 2],mapx, mapy,Arrays.toString(state) )); // | |
* printMap(scope_map); | |
* | |
* if (mapx < 0 || mapy < 0 || mapx > 10 || mapy > 10) return false; else if | |
* (!scope_map[mapy][mapx]) { // System.out.println("Error!"); return false; | |
* } else { scope_map[mapy][mapx] = false; } } } return true; } | |
*/ | |
public static void main(String[] args) throws Exception { | |
initMap(); | |
viz = new Viz(); | |
// printMap(); | |
LinkedList<State> path = BFS(); | |
printAnswer(path); | |
System.out.println(path.size()); | |
} | |
private static void printMap(boolean[][] map) { | |
for (boolean[] row : map) { | |
for (boolean bool : row) { | |
System.out.print((bool) ? " " : 0); | |
} | |
System.out.println(); | |
} | |
System.out.println(); | |
} | |
private static void initMap() { | |
map = new boolean[10][10]; | |
for (boolean[] row : map) | |
Arrays.fill(row, true); | |
for (int i = 0; i < 10; i++) { | |
map[i][0] = false; | |
map[i][9] = false; | |
} | |
for (int i = 1; i < 9; i++) { | |
map[0][i] = false; | |
map[9][i] = false; | |
} | |
map[1][1] = false; | |
map[1][2] = false; | |
map[2][1] = false; | |
map[7][1] = false; | |
map[8][1] = false; | |
map[8][2] = false; | |
map[1][7] = false; | |
map[1][8] = false; | |
map[2][8] = false; | |
map[8][7] = false; | |
map[7][8] = false; | |
map[8][8] = false; | |
map[3][4] = false; | |
map[4][4] = false; | |
map[4][3] = false; | |
} | |
private static void hardcodeStates() { | |
byte[] state = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | |
ArrayList<State> return_states = new ArrayList<State>(); | |
byte[][] possible_states = new byte[44][22]; | |
for (int i = 0; i < 11; i++) { | |
byte[] possible_state_up = Arrays.copyOf(state, state.length); | |
byte[] possible_state_down = Arrays.copyOf(state, state.length); | |
byte[] possible_state_left = Arrays.copyOf(state, state.length); | |
byte[] possible_state_right = Arrays.copyOf(state, state.length); | |
possible_state_up[i * 2 + 1] = (byte) (possible_state_up[i * 2 + 1] - 1); | |
possible_states[i * 4] = Arrays.copyOf(possible_state_up, possible_state_up.length); | |
possible_state_down[i * 2 + 1] = (byte) (possible_state_down[i * 2 + 1] + 1); | |
possible_states[i * 4 + 1] = Arrays.copyOf(possible_state_down, possible_state_down.length); | |
possible_state_left[i * 2] = (byte) (possible_state_left[i * 2] - 1); | |
possible_states[i * 4 + 2] = Arrays.copyOf(possible_state_left, possible_state_left.length); | |
possible_state_right[i * 2] = (byte) (possible_state_right[i * 2] + 1); | |
possible_states[i * 4 + 3] = Arrays.copyOf(possible_state_right, possible_state_right.length); | |
} | |
for (int i = 0; i < 44; i++) { | |
System.out.print("{"); | |
for (int j = 0; j < 22; j++) { | |
System.out.print(possible_states[i][j] + ","); | |
} | |
System.out.print("}"); | |
System.out.println(); | |
} | |
} | |
private static void printAnswer(LinkedList<State> states) { | |
for (State state : states) { | |
System.out.println(String.format("(%1$s,%2$s) (%3$s,%4$s) (%5$s,%6$s) (%7$s,%8$s) (%9$s,%10$s) (%11$s,%12$s) (%13$s,%14$s) (%15$s,%16$s) (%17$s,%18$s) (%19$s,%20$s) (%21$s,%22$s) ", state.state[0],state.state[1],state.state[2],state.state[3],state.state[4],state.state[5],state.state[6],state.state[7],state.state[8],state.state[9],state.state[10],state.state[11],state.state[12],state.state[13],state.state[14],state.state[15],state.state[16],state.state[17],state.state[18],state.state[19],state.state[20],state.state[21])); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main; | |
public class State { | |
State parent; | |
byte[] state; | |
public State(State parent) { | |
this.parent = parent; | |
this.state = new byte[22]; | |
} | |
public State(State parent, byte[] state) { | |
this.parent = parent; | |
this.state = state; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment