2009-09-15 214 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