Skip to main content
added 9 characters in body
Source Link
Ingo
  • 274
  • 2
  • 5

ThisThe following code

This code

The following code

putting things right ... i hope
Source Link
Ingo
  • 274
  • 2
  • 5

EDIT


I am sorry if I upset some of you. My only intention was to show a way how to avoid a stack overflow. I probably should have written a full code example instead of just a small piece of a quickly written and rough code excerpt.

This code

  • avoids recursion as I use calculate the required values iteratively.
  • includes memoization as Values already calculated are stored away and retrieved if already calculated
  • also includes a stopwatch, so you can see that memoization works properly

...umm... if you run it make sure you set your command shell window to have a buffer of 9999 lines... the usual 300 will not be enough to run through the results of the below program...

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace ConsoleApplication1
{
    class Program
    {
        static Stopwatch w = new Stopwatch();
        static Faculty f = Faculty.GetInstance();

        static void Main(string[] args)
        {
            Out(5);
            Out(10);
            Out(-5);
            Out(0);
            Out(1);
            Out(4);
            Out(29);
            Out(30);
            Out(20);
            Out(10000);
            Out(20000);
            Out(19999);
            Console.ReadKey();
        }

        static void Out(BigInteger n)
        {
             try
            {
                w.Reset();
                w.Start();
                var x = f.Calculate(n);
                w.Stop();
                var time = w.ElapsedMilliseconds;
                Console.WriteLine(String.Format("{0} ({2}ms): {1}", n, x, time));
            }
            catch (ArgumentException e)
            {
                Console.WriteLine(e.Message);
            }

            Console.WriteLine("\n\n");
       }
    }

I declare

  • 1 static variable "instance" in the Faculty class to a store a singleton. That way as long as your program is running, whenever you "GetInstance()" of the class you get the instance that has stored all values already calculated.
  • 1 static SortedList which will hold all the values already calculated

In the constructor I also add 2 special values of the list 1 for inputs 0 and 1.

    public class Faculty
    {
        private static SortedList<BigInteger, BigInteger> _values; 
        private static Faculty _faculty {get; set;}

        private Faculty ()
        {
            _values = new SortedList<BigInteger, BigInteger>();
            _values.Add(0, 1);
            _values.Add(1, 1);
        }

        public static Faculty GetInstance() {
            _faculty = _faculty ?? new Faculty();
            return _faculty;
        }

        public BigInteger Calculate(BigInteger n) 
        {
            // check if input is smaller 0
            if (n < 0)
                throw new ArgumentException(" !!! Faculty is not defined for values < 0 !!!");

            // if value is not already calculated => do so
            if(!_values.ContainsKey(n))
                Faculties(n);
        
            // retrieve n! from Sorted List
            return _values[n];
        }

        private static void Faculties(BigInteger n)
        {
            // get the last calculated values and continue calculating if the calculation for a bigger n is required
            BigInteger i = _values.Max(x => x.Key),
                           result = _values[i];
            
            while (++i <= n)
            {
                CalculateNext(ref result, i);
                // add value to the SortedList if not already done
                if (!_values.ContainsKey(i))
                    _values.Add(i, result);
            }
        }

        private static void CalculateNext(ref BigInteger lastresult, BigInteger i) {

            // put in whatever iterative calculation step you want to do
            lastresult = lastresult * i;

        }
    }
}

EDIT


I am sorry if I upset some of you. My only intention was to show a way how to avoid a stack overflow. I probably should have written a full code example instead of just a small piece of a quickly written and rough code excerpt.

This code

  • avoids recursion as I use calculate the required values iteratively.
  • includes memoization as Values already calculated are stored away and retrieved if already calculated
  • also includes a stopwatch, so you can see that memoization works properly

...umm... if you run it make sure you set your command shell window to have a buffer of 9999 lines... the usual 300 will not be enough to run through the results of the below program...

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace ConsoleApplication1
{
    class Program
    {
        static Stopwatch w = new Stopwatch();
        static Faculty f = Faculty.GetInstance();

        static void Main(string[] args)
        {
            Out(5);
            Out(10);
            Out(-5);
            Out(0);
            Out(1);
            Out(4);
            Out(29);
            Out(30);
            Out(20);
            Out(10000);
            Out(20000);
            Out(19999);
            Console.ReadKey();
        }

        static void Out(BigInteger n)
        {
             try
            {
                w.Reset();
                w.Start();
                var x = f.Calculate(n);
                w.Stop();
                var time = w.ElapsedMilliseconds;
                Console.WriteLine(String.Format("{0} ({2}ms): {1}", n, x, time));
            }
            catch (ArgumentException e)
            {
                Console.WriteLine(e.Message);
            }

            Console.WriteLine("\n\n");
       }
    }

I declare

  • 1 static variable "instance" in the Faculty class to a store a singleton. That way as long as your program is running, whenever you "GetInstance()" of the class you get the instance that has stored all values already calculated.
  • 1 static SortedList which will hold all the values already calculated

In the constructor I also add 2 special values of the list 1 for inputs 0 and 1.

    public class Faculty
    {
        private static SortedList<BigInteger, BigInteger> _values; 
        private static Faculty _faculty {get; set;}

        private Faculty ()
        {
            _values = new SortedList<BigInteger, BigInteger>();
            _values.Add(0, 1);
            _values.Add(1, 1);
        }

        public static Faculty GetInstance() {
            _faculty = _faculty ?? new Faculty();
            return _faculty;
        }

        public BigInteger Calculate(BigInteger n) 
        {
            // check if input is smaller 0
            if (n < 0)
                throw new ArgumentException(" !!! Faculty is not defined for values < 0 !!!");

            // if value is not already calculated => do so
            if(!_values.ContainsKey(n))
                Faculties(n);
        
            // retrieve n! from Sorted List
            return _values[n];
        }

        private static void Faculties(BigInteger n)
        {
            // get the last calculated values and continue calculating if the calculation for a bigger n is required
            BigInteger i = _values.Max(x => x.Key),
                           result = _values[i];
            
            while (++i <= n)
            {
                CalculateNext(ref result, i);
                // add value to the SortedList if not already done
                if (!_values.ContainsKey(i))
                    _values.Add(i, result);
            }
        }

        private static void CalculateNext(ref BigInteger lastresult, BigInteger i) {

            // put in whatever iterative calculation step you want to do
            lastresult = lastresult * i;

        }
    }
}
added 61 characters in body
Source Link
Ingo
  • 274
  • 2
  • 5

Memoisation: you could create an Enumeration that will replace the recursion... here is an example for calculating faculty doing that... (wont work for big numbers as i only used long in the example :-))

public class Faculty
{

    public static IEnumerable<long> Faculties(long n)
    {
        long stopat = n;

        long x = 1;
        long result = 1;

        while (x <= n)
        {
            result = result * x;
            yield return result;
            x++;
        }
    }
}

even if this is not memoization, this way you will void a stack overflow

Memoisation: you could create an Enumeration that will replace the recursion... here is an example for calculating faculty doing that... (wont work for big numbers as i only used long in the example :-))

public class Faculty
{

    public static IEnumerable<long> Faculties(long n)
    {
        long stopat = n;

        long x = 1;
        long result = 1;

        while (x <= n)
        {
            result = result * x;
            yield return result;
            x++;
        }
    }
}

you could create an Enumeration that will replace the recursion... here is an example for calculating faculty doing that... (wont work for big numbers as i only used long in the example :-))

public class Faculty
{

    public static IEnumerable<long> Faculties(long n)
    {
        long stopat = n;

        long x = 1;
        long result = 1;

        while (x <= n)
        {
            result = result * x;
            yield return result;
            x++;
        }
    }
}

even if this is not memoization, this way you will void a stack overflow

Source Link
Ingo
  • 274
  • 2
  • 5
Loading