factorial of n numbers using c# lambda..?

后端 未结 4 922
名媛妹妹
名媛妹妹 2020-12-17 02:01

I just started playing with lambdas and Linq expression for self learning. I took the simple factorial problem for this. with the little complex scenario where find the fact

相关标签:
4条回答
  • 2020-12-17 02:16

    Just to continue on Jon's answer, here's how you can memoize the factorial function so that you don't recompute everything at each step :

    public Func<T, TResult> Memoize<T, TResult>(Func<T, TResult> func)
    {
        Dictionary<T, TResult> _resultsCache = new Dictionary<T, TResult>();
     return (arg) =>
     {
         TResult result;
         if (!_resultsCache.TryGetValue(arg, out result))
      {
       result = func(arg);
       _resultsCache.Add(arg, result);
      }
      return result;
     };
    }
    
    ...
    
    Func<int, int> factorial = null; // Just so we can refer to it
    factorial = x => x <= 1 ? 1 : x * factorial(x-1);
    var factorialMemoized = Memoize(factorial);
    var res = Enumerable.Range(1, 10).Select(x => factorialMemoized(x));
    foreach (var outt in res)
        Console.WriteLine(outt.ToString());
    

    EDIT: actually the code above is not correct, because factorial calls factorial, not factorialMemoized. Here's a better version :

    Func<int, int> factorial = null; // Just so we can refer to it
    Func<int, int> factorialMemoized = null;
    factorial = x => x <= 1 ? 1 : x * factorialMemoized(x-1);
    factorialMemoized = Memoize(factorial);
    var res = Enumerable.Range(1, 10).Select(x => factorialMemoized(x));
    foreach (var outt in res)
        Console.WriteLine(outt.ToString());
    

    With that code, factorial is called 10 times, against 55 times for the previous version

    0 讨论(0)
  • 2020-12-17 02:17

    I tried to come up with something resembling F#'s scan function, but failed since my LINQ isn't very strong yet.

    Here's my monstrosity:

    //this is similar to the folowing F# code: 
    //let result = [1..10] |> List.scan (fun acc n -> acc*n) 1
    
    var result = 
        Enumerable.Range(1, 10)
            .Aggregate(new List<int>(new[] { 1 }),
                        (acc, i) => {
                                acc.Add(i * acc.Last());
                                return acc;
                            }
                       );
    
    foreach(var num in result) Console.WriteLine("{0}",num);
    

    If anyone knows if there actually is an equivalent of F#'s scan function in LINQ that I missed, I'd be very interested.

    0 讨论(0)
  • 2020-12-17 02:22

    Simple although no recursion here:

    public static int Factorial(this int count)
    {
            return count == 0
                       ? 1
                       : Enumerable.Range(1, count).Aggregate((i, j) => i*j);
    }
    
    3.Factorial() == 6
    
    0 讨论(0)
  • 2020-12-17 02:25

    Currently there's no recursion - that's the problem. You're just taking a sequence of numbers, and projecting each number to "itself * itself-1".

    The simple and inefficient way of writing a factorial function is:

    Func<int, int> factorial = null; // Just so we can refer to it
    factorial = x => x <= 1 ? 1 : x * factorial(x-1);
    
    for (int i = 1; i <= range; i++)
    {
        Console.WriteLine(factorial(i));
    }
    

    Typically you then get into memoization to avoid having to repeatedly calculate the same thing. You might like to read Wes Dyer's blog post on this sort of thing.

    0 讨论(0)
提交回复
热议问题