факториал из n чисел с использованием c # лямбда ..? - PullRequest
6 голосов
/ 15 сентября 2009

Я только начал играть с лямбдами и выражениями 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, range).
  • выберите каждое число х и снова зациклите их до х раз (вместо рекурсия)
  • и выберите числа Где (y => (y> 1)) больше 1 и умножьте это на (у-1)

я знаю, что где-то напутал. может кто-нибудь сказать мне, что не так и любое другое возможное решение.

EDIT:

Я собираюсь позволить этой теме открыться на некоторое время ... так как это мои первые шаги к лямбде. Я нашел все ответы очень полезными и информативными. способы решения этой проблемы.

Ответы [ 4 ]

22 голосов
/ 15 сентября 2009

В настоящее время нет рекурсии - вот в чем проблема. Вы просто берете последовательность чисел и проецируете каждое число на "себя * себя -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));
}

Как правило, вы попадаете в памятку , чтобы избежать необходимости повторять одно и то же. Вы можете прочитать сообщение в блоге Уэса Дайера о подобных вещах.

8 голосов
/ 29 сентября 2010

Простой, хотя здесь нет рекурсии:

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

3.Factorial() == 6
6 голосов
/ 15 сентября 2009

Просто чтобы продолжить ответ Джона, вот как вы можете запомнить функцию факториала, чтобы не пересчитывать все на каждом этапе:

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 голосов
/ 15 сентября 2009

Я пытался придумать что-то похожее на функцию сканирования 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);

Если кто-нибудь знает, есть ли на самом деле эквивалент функции сканирования F # в LINQ, который я пропустил, я был бы очень заинтересован.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...