import java.util.*;

/***
Recursive definition of towers of hanoi
	to move a single disc from 'source' to 'dest' using 'aux' as auxiliary: simply move the disc from 'source' to 'dest'
	to move a n discs from 'source' to 'dest' using 'aux' as auxiliary: 
		move n-1 discs from 'source' to 'aux' using 'dest' as auxiliary
		move disc n from 'source' to 'dest'
		move n-1 discs from 'aux' to 'dest' using 'source' as auxiliary
***/

public class TowersWithTracing {
	public static void main(String [] args) {
		Scanner keyboard = new Scanner(System.in);

		System.out.print("How many rings? ");
		int n = keyboard.nextInt();

		System.out.println(indentation + "Calling towers(" + n + ", " + 'A' + ", " + 'B' + ", " + 'C' + ") from main");
		towers(n, 'A', 'B', 'C');
	}

	static void towers(int n, char source, char aux, char dest) {
		indent();
		System.out.println(indentation + "Entering towers(" + n + ", " + source + ", " + aux + ", " + dest + ")");

		if (n == 1) {
			System.out.println(indentation + "Encountered escape clause of n=1");
			System.out.println("*** Move disc 1 from " + source + " to " + dest);
		}
		else {
			System.out.println(indentation + "Calling towers(" + (n-1) + ", " + source + ", " + dest + ", " + aux + ") recursively (first recursive call)");
			towers(n-1, source, dest, aux);
			System.out.println(indentation + "Returned to towers(" + (n) + ", " + source + ", " + aux + ", " + dest + ") from first recursive call");

			System.out.println("*** Move disc " + n + " from " + source + " to " + dest);
			System.out.println(indentation + "Calling towers(" + (n-1) + ", " + aux + ", " + source + ", " + dest + ") recursively (second recursive call)");
			towers(n-1, aux, source, dest);
			System.out.println(indentation + "Returned to towers(" + (n) + ", " + source + ", " + aux + ", " + dest + ") from second recursive call");
		}

		System.out.println(indentation + "Exiting towers(" + n + ", " + source + ", " + aux + ", " + dest + ")");
		exdent();
	}

	static String indentation = "";
	static void indent() {indentation += "|  ";}
	static void exdent() {indentation = indentation.substring(3);}

}
