Reve’s puzzle is identical to the towers of Hanoi problem, except that there are 4 poles (instead of 3). The task is to move n discs of different sizes from the starting pole to the destination pole, while obeying the following rules:
The following remarkable algorithm, discovered by Frame and Stewart in 1941, transfers n discs from the starting pole to the destination pole using the fewest moves (although this fact was not proven until 2014).
Write a program RevesPuzzle.java that takes an integer command-line argument n and prints a solution to Reve’s puzzle. Assume that the the discs are labeled in increasing order of size from 1 to n and that the poles are labeled A, B, C, and D, with A representing the starting pole and D representing the destination pole. Here are a few sample executions:
~/Desktop/recursion> java RevesPuzzle 3
Move disc 1 from A to B
Move disc 2 from A to C
Move disc 3 from A to D
Move disc 2 from C to D
Move disc 1 from B to D
~/Desktop/recursion> java RevesPuzzle 4
Move disc 1 from A to D
Move disc 2 from A to B
Move disc 1 from D to B
Move disc 3 from A to C
Move disc 4 from A to D
Move disc 3 from C to D
Move disc 1 from B to A
Move disc 2 from B to D
Move disc 1 from A to D
~/Desktop/recursion> java RevesPuzzle 5
Move disc 1 from A to D
Move disc 2 from A to C
Move disc 3 from A to B
Move disc 2 from C to B
Move disc 1 from D to B
Move disc 4 from A to C
Move disc 5 from A to D
Move disc 4 from C to D
Move disc 1 from B to A
Move disc 2 from B to C
Move disc 3 from B to D
Move disc 2 from C to D
Move disc 1 from A to D
Note: you may assume that n is a positive integer.
Recall that for the towers of Hanoi problem, the minimum number of moves for a 64-disc problem is 264 − 1. With the addition of a fourth pole, the minimum number of moves for a 64-disc problem is reduced to 18,433.
public class RevesPuzzle {
private static void reves(int n, char a, char b, char c, char d) {
if (n == 1) {
StdOut.println("Move disc " + n + " from " + a + " to " + d);
return;
}
final int k = (int) Math.round(n + 1.0 - (Math.sqrt((2 * n) + 1.0)));
// transfer k smallest discs from (A) to single pole (B)
// other than start or destination pole
reves(k, a, c, d, b);
// transfer remaining n-k discs from (A) to destination (D)
// and skip (B)
hanoi(n, k, a, c, d);
// transfer k smallest discs from (B) to destination (D)
reves(k, b, a, c, d);
}
private static void hanoi(int n, int k, char start, char mid, char end) {
if ((n == 0) || (n <= k)) {
return;
}
hanoi(n - 1, k, start, end, mid);
StdOut.println("Move disc " + n + " from " + start + " to " + end);
hanoi(n - 1, k, mid, start, end);
}
public static void main(String[] args) {
final int n = Integer.parseInt(args[0]);
reves(n, 'A', 'B', 'C', 'D');
}
}
Link To: Java Source Code