使用c#lambda的n个数的阶乘...?

时间:2009-09-15 11:57:10

标签: c# linq lambda

我刚开始玩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 - Enumerable.Range(1,范围)。
  • 选择每个数字x并再次循环它们x次(而不是 递归)
  • 并选择数字其中(y =>(y> 1))大于1并将其乘以 的(Y-1)

我知道我搞砸了某个地方。谁能告诉我什么是错的以及任何其他可能的解决方案。

修改

我打算让这个线程打开一段时间......因为这是我迈向lambda的最初步骤...我发现所有的答案都非常有用且信息丰富..而且它会很有趣而且学习看到不同的解决这个问题的方法。

4 个答案:

答案 0 :(得分:22)

目前没有递归 - 这就是问题所在。你只是采用一系列数字,并将每个数字投射到“本身*本身-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

答案 1 :(得分:8)

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

public static int Factorial(this int count)
{
        return count == 0
                   ? 1
                   : Enumerable.Range(1, count).Aggregate((i, j) => i*j);
}

3.Factorial() == 6

答案 2 :(得分:6)

为了继续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调用了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());

使用该代码,factorial被调用10次,而之前版本被调用55次

答案 3 :(得分:3)

我尝试提出类似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#扫描功能,我会非常感兴趣。