我正在尝试解决Project Euler中的一个问题,它正在创建一个直到400万的斐波纳契系列,并添加系列中的偶数,这显然是非常容易的任务,我在2分钟内回答它,< / p>
int result=2;
int first=1;
int second=2;
int i=2;
while (i < 4000000)
{
i = first + second;
if (i % 2 == 0)
{
result += i;
}
first = second;
second = i;
}
Console.WriteLine(result);
但我想用lambda表达式
来做我的努力就像
DelType del = (oldVal, newVal) =>((oldVal==0?1:newVal + newVal==1?2:oldVal+newVal) % 2 == 0) ? oldVal + newVal : 0;
int a=del(0, 1);
请建议如何完成这项工作
答案 0 :(得分:16)
我的第一个答案是完全误读了这个问题,但现在我重读了它(感谢MagnatLU!)我建议这个不适合lambda表达式。但是,对于迭代器块和LINQ的组合,它是辉煌的:
// Using long just to avoid having to change if we want a higher limit :)
public static IEnumerable<long> Fibonacci()
{
long current = 0;
long next = 1;
while (true)
{
yield return current;
long temp = next;
next = current + next;
current = temp;
}
}
...
long evenSum = Fibonacci().TakeWhile(x => x < 4000000L)
.Where(x => x % 2L == 0L)
.Sum();
答案 1 :(得分:7)
使用此递归函数
Func<int, int> fib = null;
fib = (x) => x > 1 ? fib(x-1) + fib(x-2) : x;
示例用法:
Console.WriteLine(fib(10));
答案 2 :(得分:7)
这是作为lambda表达式的oneliner:
Func<int, int, int, int, int> fib = null;
fib = (n, a, b, res) => n == 0 ? res : fib(n - 1, b, a + b, n % 2 == 0 ? res : res + a + b);
// usage: fib(n, 1, 0, 0)
它在x64上使用O(n)堆栈空间和O(n)时间,在x64上使用O(1)堆栈空间(由于x64 JIT上的尾部递归优化),因此在32-上n = 400000时将失败位系统。
编辑:它从头到尾计算系列的元素,而不是开头,但是你应该知道如何用tailrec做λ。
答案 3 :(得分:1)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Fibonacci : IEnumerable<int>{
delegate Tuple<int,int> update(Tuple<int,int> x);
update func = ( x ) => Tuple.Create(x.Item2, x.Item1 + x.Item2);
public IEnumerator<int> GetEnumerator(){
var x = Tuple.Create<int,int>(0,1);
while (true){
yield return x.Item1;
x = func(x);
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
class Sample {
static public void Main(){
int result= (new Fibonacci()).TakeWhile(x => x < 4000000).Where(x => x % 2 == 0).Sum();
Console.WriteLine(result);//4613732
}
}
OTHER
public static class Seq<T>{
public delegate Tuple<T,T> update(Tuple<T,T> x);
static public IEnumerable<T> unfold(update func, Tuple<T,T> initValue){
var value = initValue;
while (true){
yield return value.Item1;
value = func(value);
}
}
}
class Sample {
static public void Main(){
var fib = Seq<int>.unfold( x => Tuple.Create<int,int>(x.Item2, x.Item1 + x.Item2), Tuple.Create<int,int>(0,1));
int result= fib.TakeWhile(x => x < 4000000).Where(x => x % 2 == 0).Sum();
Console.WriteLine(result);
}
}
答案 4 :(得分:1)
与Func双线程类似,现在具有本地功能,可以这样做:
int Fibonacci(int i) => i <= 1 ? i : Fibonacci(i - 1) + Fibonacci(i - 2);
答案 5 :(得分:0)
你知道你可以这样做:
Func<int,int,int> func = (first, second) => {
var result=2;
int i=2;
while (i < 4000000)
{
i = first + second;
if (i % 2 == 0)
{
result += i;
}
first = second;
second = i;
}
return result;
};
答案 6 :(得分:0)
如果您想要一个纯粹的递归lambda解决方案,请查看this answer以获取显示其完成方式的文章的几个链接。
然而,对我来说,那些超级东西太疯狂了,所以我最好再按照已经存在的另一个答案。
答案 7 :(得分:0)
我知道这是一个老问题,但我今天正在解决同样的问题,并且在O(n)运行时间的情况下得出了这个简洁的功能式解决方案:
static int FibTotal(int limit, Func<int, bool> include, int last = 0, int current = 1)
{
if (current < limit)
return FibTotal(limit, include, current, last + current) +
(include(current) ? current : 0);
else
return 0;
}
如果你首先定义这个便利类(也许这样的东西已经存在于.NET框架中,但我无法找到它),你也可以得到一个很好的单行解决方案:
public static class Sequence
{
public static IEnumerable<T> Generate<T>(T seed, Func<T, T> next)
{
while (true)
{
yield return seed;
seed = next(seed);
}
}
}
然后解决方案变为:
var result = Sequence.Generate(Tuple.Create(1, 1),
t => Tuple.Create(t.Item2, t.Item1 + t.Item2))
.Select(t => t.Item1)
.TakeWhile(i => i < 4000000)
.Where(i=> i % 2 == 0)
.Sum();
答案 8 :(得分:0)
public static void fibSeriesEx3()
{
List<int> lst = new List<int> { 0, 1 };
for (int i = 0; i <= 10; i++)
{
int num = lst.Skip(i).Sum();
lst.Add(num);
foreach (int number in lst)
Console.Write(number + " ");
Console.WriteLine();
}
}
答案 9 :(得分:0)
一种有效的衬垫:
Func<int, int, int, int, int> fib = null;
fib = (a, b, counter, n) => counter < n ? fib(b, a + b, counter+1, n) : a;
//print the 9th fib num
Console.WriteLine(fib(0,1,1,9));
输出:21