private List<Board> solve(Board initial) { Board twin = initial.twin(); MinPQ<SearchNode> mainQueue = new MinPQ<>(); MinPQ<SearchNode> twinQueue = new MinPQ<>(); mainQueue.insert(new SearchNode(initial, 0, null)); twinQueue.insert(new SearchNode(twin, 0, null)); while (true) { SearchNode mainSearch = mainQueue.delMin(); SearchNode twinSearch = twinQueue.delMin(); if (mainSearch.board.isGoal()) { return retraceSteps(mainSearch); } if (twinSearch.board.isGoal()) { return null; } for (Board board : mainSearch.board.neighbors()) { SearchNode mainPrevious = mainSearch.previous; if (mainPrevious == null || !board.equals(mainPrevious.board)) { mainQueue.insert(new SearchNode(board, mainSearch.moves + 1, mainSearch)); } } for (Board board : twinSearch.board.neighbors()) { SearchNode twinPrevious = twinSearch.previous; if (twinPrevious == null || !board.equals(twinPrevious.board)) { twinQueue.insert(new SearchNode(board, twinSearch.moves + 1, twinSearch)); } } } }
public static void main(String[] args) { int[][] blocks = { {1, 2, 3}, {4, 5, 6}, {7, 8, 0} }; Board b = new Board(blocks); // b.isGoal(); // System.out.println(b.isGoal()); // System.out.println(b.dimension()); System.out.println(b.toString()); // System.out.println( b.calcManhattan(0,0) ); // System.out.println( b.calcManhattan(0,1) ); for (Board n : b.neighbors()) { System.out.println(n.toString()); System.out.println(); } Board twin = b.twin(); System.out.println("\n TWIN: \n" + twin.toString()); }
public static void main(String[] args) { // unit tests (not graded) In in = new In(args[0]); // input file int N = in.readInt(); int[][] blocks = new int[N][N]; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) blocks[i][j] = in.readInt(); Board bd = new Board(blocks); StdOut.println("dimension: " + bd.dimension()); StdOut.println("hamming: " + bd.hamming()); StdOut.println("Manhattan distances: " + bd.manhattan()); StdOut.println("is goal: " + bd.isGoal()); StdOut.print(bd); StdOut.print("twin: " + bd.twin()); StdOut.println("twin equal: " + bd.equals(bd.twin())); StdOut.println("twin twin equal: " + bd.equals(bd.twin().twin())); for (Board it : bd.neighbors()) StdOut.print(it); }
@Test public void testTwin() { int[][] orig = {{8, 1, 3}, {4, 0, 2}, {7, 6, 5}}; Board twin = new Board(new int[][] {{1, 8, 3}, {4, 0, 2}, {7, 6, 5}}); Board b = new Board(orig); Board curr = b.twin(); assertEquals(twin, curr); int[][] twin2 = {{1, 8, 0}, {3, 4, 2}, {7, 6, 5}}; Board o2 = new Board(new int[][] {{1, 8, 0}, {4, 3, 2}, {7, 6, 5}}); Board b2 = new Board(twin2); curr = b2.twin(); assertEquals(o2, curr); }
// find a solution to the initial board (using the A* algorithm) public Solver(Board initial) { Board twin = initial.twin(); SearchNode minNode = null; boolean isTwinRound = false; MinPQ<SearchNode> currentPQ = null; minPQ.insert(new SearchNode(initial)); minPQForTwin.insert(new SearchNode(twin)); while (true) { // Searching solution in the initial board and and its twin board // simultaneously(alternating in loops). // It has been proven by Math theory that exactly one of the two // will lead to the goal board. If a solution is found in the twin // board, it immediately proves that the initial board is not solvable, // and the search will terminate there. // Otherwise, the initial board will reach a solution. if (isTwinRound) { currentPQ = minPQForTwin; } else { currentPQ = minPQ; } minNode = currentPQ.delMin(); if (minNode.getBoard().isGoal()) { break; } else { for (Board neighbor : minNode.getBoard().neighbors()) { // Insert the neighbors into the MinPQ if: // 1. Current node contains the initial board(has no prev node) // 2. The new neighbor is not the same as current node's previous search node. // This is a critical optimization used to reduce unnecessary // exploration of already visited search nodes. if (minNode.getPrev() == null || !neighbor.equals(minNode.getPrev().getBoard())) { currentPQ.insert(new SearchNode(neighbor, minNode)); } } // Flip the state of the isTwinRound flag isTwinRound = isTwinRound ? false : true; } } if (isTwinRound) { isSolvable = false; solution = null; } else { isSolvable = true; solution = minNode; moves = solution.getMoves(); } }
/** * find a solution to the initial board (using the A* algorithm) * * @param initial */ public Solver(Board initial) { Thread t1 = createSolveThread(initial, false); Thread t2 = createSolveThread(initial.twin(), true); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } }
/** * main for unit tests * * @param args */ public static void main(String[] args) { In in = new In(args[0]); int N = in.readInt(); int[][] blocks = new int[N][N]; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { blocks[i][j] = in.readInt(); } } Board initial = new Board(blocks); // test StdOut.println(initial.dimension()); StdOut.println(initial.hamming()); StdOut.println(initial.manhattan()); StdOut.println(initial.isGoal()); StdOut.println(initial.toString()); StdOut.println(initial.twin().toString()); for (Board b : initial.neighbors()) { StdOut.println(b.toString()); } }
public Solver(Board initial) // find a solution to the initial board (using the A* algorithm) { initQueue = GetSolution(initial); twinQueue = GetSolution(initial.twin()); }