// Arup Guha
// 4/2/2024
// Code showing justification and how to turn regular recursion into DP.
// Illustrates solution to the Fibonacci problem.

import java.util.*;

public class dplearn {

	public static void main(String[] args) {
	
		// Call function and time it.
		/*
		long sT = System.currentTimeMillis();
		long x = fib(48);
		long eT = System.currentTimeMillis();
		System.out.println("fib of 48 is "+x+" took "+(eT-sT)+" ms.");
		*/
		int n = 48;
		
		// My storage table, -1 means not solved yet.
		long[] memo = new long[n+1];
		Arrays.fill(memo, -1);
		long sT = System.currentTimeMillis();
		long x = fibdp(48);
		long eT = System.currentTimeMillis();
		System.out.println("fib of 48 is "+x+" took "+(eT-sT)+" ms.");
	}

	public static long fib(int n) {
	
		// fib(0) = 0, fib(1) = 1
		if (n < 2) return n;
		
		// Solve recursively.
		return fib(n-1)+fib(n-2);
	}
	
	// memoized version of fibonacci
	public static long fibmemo(int n, long[] memo) {
	
		// fib(0) = 0, fib(1) = 1
		if (n < 2) return n;
		
		// Hey, I finally remembered what my wife told me!
		if (memo[n] != -1) return memo[n];
		
		// Before I return, be smart, store the answer in my memory!!!
		return memo[n] = fibmemo(n-1, memo)+fibmemo(n-2, memo);
	}

	// DP version.
	public static long fibdp(int n) {
		
		// Create table put in base cases.
		long[] fibs = new long[n+1];
		fibs[1] = 1;
		
		// Compute each fibonacci number and return.
		for (int i=2; i<=n; i++)
			fibs[i] = fibs[i-1] + fibs[i-2];
		
		// Ta da!
		return fibs[n];
		
	}
}