代码之家  ›  专栏  ›  技术社区  ›  RameshVel

用C lambda求n个数的阶乘…?

  •  6
  • RameshVel  · 技术社区  · 15 年前

    我刚开始玩lambdas和linq表情自学。我用了简单的阶乘问题。在一个小的复杂场景中,找到给定n个数的阶乘(使用递归循环)。

    低于我尝试的代码。但这不起作用。

    public void FindFactorial(int range)
    {
    
        var res = Enumerable.Range(1, range).Select(x => Enumerable.Range(0, x).Where(y => (y > 1)).Select(y => y * (y-1)));            
        foreach (var outt in res)
            Console.WriteLine(outt.ToString());
    
    }
    

    这是我用的程序

    • 循环使用数字1到n-- 可枚举。范围(1,范围)。
    • 选择每个数字x,然后再次循环它们到x次(而不是 递归)
    • 然后选择号码 其中(y=>(y>1)) 大于1并乘以 (Y-1)

    我知道我把什么地方搞砸了。有人能告诉我出了什么问题和其他可能的解决办法吗?

    编辑:

    我要让这条线打开一段时间…因为这是我迈向lambda的第一步……我发现所有的答案都很有用,也很有用。看到解决这个问题的不同方法,这将是有趣和伟大的学习。

    4 回复  |  直到 14 年前
        1
  •  22
  •   Jon Skeet    14 年前

    目前没有递归——这就是问题所在。你只需要取一个数字序列,然后将每个数字投影到“自身1”。

    编写阶乘函数的简单而低效的方法是:

    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));
    }
    

    通常你会进入 memoization 为了避免重复计算相同的东西。你可能想看 Wes Dyer's blog post 在这类事情上。

        2
  •  7
  •   Gluip    14 年前

    虽然这里没有递归,但很简单:

    public static int Factorial(this int count)
    {
            return count == 0
                       ? 1
                       : Enumerable.Range(1, count).Aggregate((i, j) => i*j);
    }
    
    3.Factorial() == 6
    
        3
  •  6
  •   Thomas Levesque    15 年前

    为了继续讨论jon的答案,下面是如何记忆阶乘函数,以便不在每个步骤中重新计算所有内容:

    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());
    

    编辑:实际上上面的代码不正确,因为 factorial 电话 阶乘 不是 factorialMemoized . 这里有一个更好的版本:

    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());
    

    有了这个代码, 阶乘 调用10次,前一版本调用55次

        4
  •  3
  •   cfern    15 年前

    我试着想出类似f的扫描功能,但失败了,因为我的LINQ还不是很强。

    这是我的怪物:

    //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);
    

    如果有人知道在我错过的linq中是否有相当于f的扫描功能,我会非常感兴趣。