package thisandthat;

import stdlib.Color;
import stdlib.StdDraw;

/*************************************************************************
 *  Compilation:  javac TowersOfHanoi.java
 *  Execution:    java TowersOfHanoi N
 *  
 *  Solves the Towers of Hanoi problem on N discs. The discs are labeled
 *  in increasing order of size from 1 to N.
 * 
 *  %  java TowersOfHanoi 3
 *  1 left
 *  2 right
 *  1 left
 *  3 left
 *  1 left
 *  2 right
 *  1 left
 *
 *  % java TowersOfHanoi 4
 *  1 right
 *  2 left
 *  1 right
 *  3 right
 *  1 right
 *  2 left
 *  1 right
 *  4 left
 *  1 right
 *  2 left
 *  1 right
 *  3 right
 *  1 right
 *  2 left
 *  1 right
 *
 *************************************************************************/

public class TowersOfHanoi {
	static StdDraw sd = new StdDraw();

    // print out instructions for moving n discs to
    // the left (if left is true) or right (if left is false)
    public static void moves(int n, boolean left) {
        if (n == 0) return;
        moves(n-1, !left);
        if (left) System.out.println(n + " left");
        else      System.out.println(n + " right");
        moves(n-1, !left);
    }
    

    // draw the current state of the Towers of Hanoi game
    public static void draw(int[] pole) {

       int N = pole.length - 1;

       // draw 3 poles
       StdDraw.clear();
       sd.setPenColor(Color.BLACK);
       sd.setPenRadius(0.002);
       for (int i = 0; i < 3; i++)
          sd.line(i, 0, i, N);

       // draw N discs
       int[] discs = new int[3];   // discs[p] = # discs on pole p
       for (int i = N; i >= 1; i--) {
          Color color = Color.getHSBColor(1.0f * i / N, .7f, .7f);
          sd.setPenColor(color);
          sd.setPenRadius(0.035);   // magic constant
          double size = 0.5 * i / N;
          int p = pole[i];
          sd.line(p-size/2, discs[p], p + size/2, discs[p]);
          ++discs[p];
       }

       sd.show(500);
    }

    public static void hanoi(int N) {
       int[] pole = new int[N+1];       // pole[i] = pole (0-2) that disc i is on
       draw(pole);
       hanoi(N, 0, 1, 2, pole);
    }

    public static void hanoi(int n, int from, int temp, int to, int[] pole) {
       if (n == 0) return;
       hanoi(n-1, from, to, temp, pole);
       System.out.println("Move disc " + n + " from pole " + from + " to pole " + to);
       pole[n] = to;
       draw(pole);
       hanoi(n-1, temp, from, to, pole);
    }

    public static void main(String[] args) {
//        int N = Integer.parseInt(args[0]);
        int N = 4;
        moves(N, true);

//      int N = Integer.parseInt(args[0]);   // number of discs
      int WIDTH  = 200;                    // width of largest disc
      int HEIGHT = 20;                     // height of each disc
        // set size of window and sale
      sd.setCanvasSize(4*WIDTH, (N+3)*HEIGHT);
        sd.setXscale(-1, 3);
        sd.setYscale(0, N+3);


        // solve the Towers of Hanoi with N discs
        hanoi(N);
    }

}
