// L-21 MCS 360 Mon 11 Oct 2010 : recursive_factorial.cpp

/* In the code below we experiment with two recursive definitions
   to compute the factorial of a natural numbers.  The functions
   that start with "trace_" give extra output to trace the execution
   of the recursive algorithm. */

#include <iostream>
using namespace std;

int factorial(int n);
// returns the factorial of n

int trace_factorial(int n);
// returns the factorial of n
// with extra output to trace the recursion

int accumulate_factorial(int n, int f);
// accumulates the factorial of n in f, 
// call with f = 1.

int trace_accumulate_factorial(int n, int f);
// accumulates the factorial of n in f, 
// call with f = 1 with extra tracing output

int main()
{
   cout << "give n : ";
   int n; cin >> n;
   cout << n << "! = "
        << factorial(n) << endl;

   cout << "tracing " << n << "! ..." << endl;
   int f = trace_factorial(n);

   int a = accumulate_factorial(n,1);
   cout << n << "! = " << a << endl;

   int b = trace_accumulate_factorial(n,1);
   cout << n << "! = " << b << endl;

   return 0;
}

int factorial(int n)
{
   if(n==0)
      return 1;
   else
      return n*factorial(n-1);
}

int trace_factorial(int n)
{
   for(int i=0; i<n; i++) cout << " ";
   cout << "n = " << n << endl; 

   if(n==0)
   {
      return 1;
      cout << "returning 1" << endl;
   }
   else
   {
      int r = n*trace_factorial(n-1);
      for(int i=0; i<n; i++) cout << " ";
      cout << "returning " << r << endl; 
      return r;
   }
}

int accumulate_factorial(int n, int f)
{
   if(n <= 1)
      return f;
   else
      return accumulate_factorial(n-1,n*f);
}  

int trace_accumulate_factorial(int n, int f)
{
   if(n <= 1)
   {
      cout << "returning " << f << endl;
      return f;
   }
   else
   { 
      cout << "computing " << n << "*" << f << endl;
      return trace_accumulate_factorial(n-1,n*f);
   }
}  

