2009-09-15 167 views
6

我刚开始玩lambdas和Linq表达自学。我为此采取了简单的因子问题。用小复杂的场景找到给定n个数字的因子(不使用递归循环)。使用c#lambda进行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)

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

编辑:

我要去让这个线程开启一段时间......因为这是我对λ初始步骤..我发现所有的答案非常有用的信息。而它去看到解决这个问题的不同方式,充满乐趣和了解更多。

回答

21

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

+3

10出来的10风格简单地对使用的 “X => X <= 1?1:X *阶乘(X-1);” .. 。x => x <= 1 :) – veggerby 2009-09-15 12:04:44

+0

感谢Jon,我已经尝试过这种方式了。但我认为它很酷这样做没有递归。感谢您的链接。 – RameshVel 2009-09-15 12:06:26

+1

+1 for memoization ...顺便说一句,有一个有趣的名为Elevate的库,它提供了一个用于记忆函数的扩展方法:http://elevate.codeplex.com/sourcecontrol/changeset/view/42940?projectName=elevate#690734 – 2009-09-15 12:15:25

6

只是为了继续对乔恩的答案,这里是你如何能memoize的阶乘的功能,这样你就不会在每一个步骤重新计算一切:

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倍的以前版本

+0

@thomas,u摇滚......我从来没有考虑过abt的memoization ..感谢给予洞见.... – RameshVel 2009-09-15 12:40:11

+0

请注意,它是更快的大值,但可能更慢对于小的值,因为字典插入和查找的开销 – 2009-09-15 17:00:48

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#的扫描功能的等效,我会很感兴趣。

+0

@cfern,谢谢你的答案..它很酷....你们给了不同的可能性,我错过了.... – RameshVel 2009-09-15 13:12:30

7

简单虽然没有递归这里:

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

3.Factorial() == 6 
+0

这是一个不错的伎俩.. 。 – RameshVel 2010-09-30 06:05:38