Pages

Towers of Hanoi Commentary

Consisting of nearly 600 lines of source code, the program presented on the Towers of Hanoi Solutions page is much longer than the ones shown below. It uses comments more liberally; it demonstrates a variety of programming constructs and techniques, including many of the mechanisms Java provides to support procedural and object-oriented programming; and it includes a non-recursive algorithm that highlights the utility of bitwise operators and exposes a fascinating connection between binary numbers and the traditional variation of the Towers of Hanoi puzzle.

Example 1

The following Java program prints a procedure for solving the traditional variation of the Towers of Hanoi puzzle.

public class TowersOfHanoi
{
    /**
     * Returns a sequence of moves that solves the specified puzzle.
     *
     *   @param    n  a non-negative integral number of disks
     *   @param from  a peg number in the set {0, 1, 2}
     *   @param   to  a different peg number, also in {0, 1, 2}
     */
    public static String solve1(int n, int from, int to)
    {
        if (n == 1)
        {
            return from + "," + to;
        }
        else
        {
            final int other   = 3 - from - to,
                      oneLess = n - 1;
            final String s1 = solve1(oneLess, from, other),
                         s2 = solve1(1, from, to),
                         s3 = solve1(oneLess, other, to);
            return s1 + "," + s2 + "," + s3;
        }
    }
    public static void main(String[] args)
    {
        final int n = Integer.parseInt(args[0]),
                  f = Integer.parseInt(args[1]),
                  t = Integer.parseInt(args[2]);
        System.out.print("[" + solve1(n, f, t) + "]");
    }
}

Example 2

The following program uses recursive methods to print the minimum number of moves required to solve variations of the Towers of Hanoi puzzle.

public class FewestMoves
{
    public static void main(String[] args)
    {
        final String message =
            "The program FewestMoves expects two integer arguments\n" +
            "n and m, where n > 0 and m is in {1, 2}. The program\n" +
            "prints the minimum number of moves required to solve\n" +
            "variations of the Towers of Hanoi puzzle that entail\n" +
            "moving up to n disks from a peg to another peg that\n" +
            "is m moves away.";
        try
        {
            final int n = Integer.parseInt(args[0]),
                      m = Integer.parseInt(args[1]);
            if (n > 0 && m > 0 && m < 3)
            {
                final String pad = "         ";
                for (Integer i = 1; i <=n; i++)
                {
                    Integer m1 = Puzzle.count1(i),
                            m2 = Puzzle.count2(i, m),
                            m3 = Puzzle.count3(i, m);
                    String  s0 = i.toString(),
                            s1 = m1.toString(),
                            s2 = m2.toString(),
                            s3 = m3.toString();
                    System.out.println(s0 +
                        pad.subSequence(0, pad.length() - s0.length()) + s1 +
                        pad.subSequence(0, pad.length() - s1.length()) + s2 +
                        pad.subSequence(0, pad.length() - s2.length()) + s3);
                }
            }
            else System.out.print(message);
        }
        catch (Exception e) { System.out.print(message); }
    }
}
class Puzzle
{
    public static int count1(int n)
    {
        if (n == 1)
            return 1;
        else // n > 1
            return 2 * count1(n-1) + 1;
    }
    public static int count2(int n, int m)
    {
        if (n == 1)
            return m;
        else if (m == 1)
            return count2(n-1, 2) + count2(n-1, 1) + 1;
        else // n > 1 and m is 2
            return 2 * count2(n, 1);
    }
    public static int count3(int n, int m)
    {
        if (m == 2) return -1; // to do

        double a = Math.pow(1 + Math.sqrt(3), n+1),
               b = Math.pow(1 - Math.sqrt(3), n+1);
        double difference =  a - b,
               product = 2 * Math.sqrt(3);
        double quotient = difference/product;
        return (int)Math.round(quotient - 1);
    }
}

Example 3

The following Java program prints a procedure for solving the variation of the Towers of Hanoi puzzle where disks can only move from peg to adjacent peg in one direction around a circle of three pegs. The solution it prints is not optimal, but it gets the job done. You can do better.

public class TowersOfHanoi
{
    /**
     * Returns a sequence of moves that solves the specified puzzle.
     *
     *   @param    n  a non-negative integral number of disks
     *   @param from  a peg number in the set {0, 1, 2}
     *   @param   to  a different peg number, also in {0, 1, 2}
     */
    public static int distance(int from, int to)
    {
        if (to < from) to += 3;
        return to - from;
    }
    public static String solve3(int n, int from, int to)
    {
        final int m = distance(from, to);
        final int other   = 3 - from - to,
                  oneLess = n - 1;
        if (n == 1)
        {
            if (m == 1)
                return from + "," + to;
            else
                return from + "," + other + "," + other + "," + to;
        }
        else
        {
            if (m == 1)
            {
                final String s1 = solve3(oneLess, from, to),
                             s2 = solve3(oneLess, to, other),
                             s3 = solve3(1, from, to),
                             s4 = solve3(oneLess, other, from),
                             s5 = solve3(oneLess, from, to);
                return s1 + "," + s2 + "," + s3 + "," + s4 + "," + s5;
            }
            else
            {
                final String s1 = solve3(n, from, other),
                             s2 = solve3(n, other, to);
                return s1 + "," + s2;
                
            }
        }
    }
    public static void main(String[] args)
    {
        try
        {
            final int n = Integer.parseInt(args[0]),
                      f = Integer.parseInt(args[1]),
                      t = Integer.parseInt(args[2]);
            System.out.print("[" + solve3(n, f, t) + "]");
        }
        catch (Exception e)
        {
            System.out.println("Snap!");
        }
    }
}