/*
 * public int Fib(int n) {
 * 	Marker 'A'
 * 	if (n == 0)
 * 		return 0;
 * 	else if (n == 2)
 * 		return 1;
 * 	else {
 * 		t1 = Fib(n-1);
 * 		Marker 'B'
 * 		t2 = Fib(n-2);
 * 		Marker 'C'
 * 		return t1+t2;
 * 	}
 * }
 */
public class StackFib {

	private static class FibFrame {
		int n;
		char nextInstruction;
		int t1, t2;
		public FibFrame(int n, char next) {
			this.n = n;
			this.nextInstruction = next;
			this.t1 = 0;
			this.t2 = 0;
		}
	}
	
	static int stackFib(int n) {
		Stack<FibFrame> stack = new Stack<FibFrame>();
		char nextInstruction = 'A';
		int returnValue=0;
		stack.push( new FibFrame(n, 'Z'));
		
		while (nextInstruction != 'Z') {
			FibFrame top = stack.top();
			if (nextInstruction == 'A') {
				if (top.n == 0) {
					nextInstruction = top.nextInstruction;
					returnValue = 0;
					stack.pop();
				}
				else if (top.n == 1) {
					nextInstruction = top.nextInstruction;
					returnValue = 1;
					stack.pop();
				}
				else {
					stack.push( new FibFrame(top.n-1, 'B'));
					nextInstruction = 'A';
				}
			}
			else  if (nextInstruction == 'B') {
				top.t1 = returnValue;
				stack.push( new FibFrame(top.n-2, 'C'));
				nextInstruction = 'A';
			}
			else if (nextInstruction == 'C') {
				top.t2 = returnValue;
				returnValue = top.t1 + top.t2;
				nextInstruction = top.nextInstruction;
				stack.pop();
			}
		}
		return returnValue;
		
	}
	
	public static void main(String[] args) {
		for (int i = 0; i < 40; i++)
			System.out.printf( "%d: %d\n", i, stackFib(i));
	}

}
