2011-12-25 47 views
5

Tôi đang cố gắng giải quyết một câu hỏi trong Project Euler, tạo chuỗi mã hóa cho đến 4 triệu và thêm số chẵn trong chuỗi, đây rõ ràng là nhiệm vụ rất dễ và tôi trả lời nó trong 2 phút,Tạo chuỗi Fibonacci sử dụng toán tử lambda

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); 

nhưng tôi muốn làm điều đó bằng cách sử dụng biểu thức lambda

Nỗ lực của tôi sẽ như

DelType del = (oldVal, newVal) =>((oldVal==0?1:newVal + newVal==1?2:oldVal+newVal) % 2 == 0) ? oldVal + newVal : 0; 

int a=del(0, 1); 

Vui lòng đề nghị làm thế nào để có được điều này thực hiện

+0

Tôi khuyên bạn nên thử làm điều đó trong câu lệnh LINQ. Đó là một chút dễ đọc hơn và sau đó bạn có thể dễ dàng chuyển đổi nó thành cú pháp lambda. –

Trả lời

15

trả lời đầu tiên của tôi đã có misread câu hỏi hoàn toàn, nhưng bây giờ tôi đã đọc lại nó (nhờ MagnatLU!) Tôi muốn đề nghị rằng đây không phải là một tốt phù hợp với các biểu thức lambda. Tuy nhiên, đó là một rực rỡ phù hợp cho một sự kết hợp của khối iterator và 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(); 
+0

heh! Tôi cũng hiểu sai. – leppie

+1

+1 cho 'lợi nhuận', trình biên dịch xấu hổ trả về' Câu lệnh lợi nhuận không thể được sử dụng bên trong một phương thức nặc danh hoặc biểu thức lambda' khi bạn cố gắng sử dụng iterator bên trong lambda trả về 'IEnumerable '. – MagnatLU

+0

@MegaMind: Tôi đang tìm một mã/dòng lệnh cho chuỗi Fibonacci. Bạn có thể giúp?? – venkat

0

Bạn biết bạn có thể làm:

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; 
             }; 
+0

Cảm ơn phản hồi của bạn, nhưng tôi muốn làm cho nó một lớp lót, – MegaMind

+1

@Manvinder - đây là một dòng ... –

+0

Tôi chỉ tò mò ... tại sao bạn cần nó trong một dòng? Tôi không biết nếu nó thậm chí có thể. – ivowiblo

6

Sử dụng hàm đệ quy này

Func<int, int> fib = null; 
fib = (x) => x > 1 ? fib(x-1) + fib(x-2) : x; 

Ví dụ Cách sử dụng:

Console.WriteLine(fib(10)); 
+1

Tôi không chắc chắn nếu nó sẽ biên dịch. Tôi có nghĩa là, có lambda tham chiếu chính nó trước khi nó được gán ... – ivowiblo

+1

@ivowiblo lambda có thể tham chiếu chính nó miễn là biến được gán trước câu lệnh trong ví dụ mã. Ví dụ: 'Func fib = null; fib = x => x> 1? fib (x - 1) + fib (x - 2): x; ' – phoog

+0

Làm cho tinh thần. Cảm ơn. – ivowiblo

7

Dưới đây là oneliner như một biểu thức lambda:

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) 

Nó sử dụng không gian ngăn xếp O (n) và thời gian O (n) trên x86 và O (1) trên không gian x64 (do tối ưu đệ quy đuôi trên x64 JIT), vì vậy nó sẽ thất bại cho n = 400000 trên 32- hệ thống bit.

Chỉnh sửa: nó đang đếm ngay cả các phần tử của chuỗi từ đầu, không phải là bắt đầu, nhưng bạn nên có ý tưởng làm thế nào để làm điều đó như λ với tailrec.

+0

Tôi không nhận được Fibonacci Series với truy vấn/biểu thức LINQ ở trên. Bắt lạm dụng/đầu ra lẻ không phải là một mã số. Tôi đã thử với 'fib (6,1,0,0)' – venkat

0

Chỉ trong trường hợp bạn muốn có giải pháp lambda đệ quy thuần túy, hãy xem this answer để biết một số liên kết đến bài viết cho biết cách thực hiện.

Tuy nhiên, nội dung uber đó quá điên rồ đối với tôi, vì vậy tôi nên làm theo một câu trả lời khác đã có ở đây.

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 
    } 
} 

KHÁC

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); 
    } 
} 
+0

Kết quả đó chắc chắn sai! nếu 'fib (30) => 832040', không có cách nào' tổng của fib (0) cho fib (4000000) => 4613732' có thể đúng – leppie

+1

@leppie Hãy chắc chắn rằng bạn nhìn thấy nó một lần nữa? fib loạt thêm tổng khi thậm chí. fib (x! = 4000000), fib (?) <4000000 – BLUEPIXY

+0

Rất tiếc, tôi đã đọc câu hỏi HOÀN TOÀN sai! – leppie

0

Tôi biết đây là một câu hỏi cũ, nhưng tôi đã làm việc trên cùng một vấn đề ngày hôm nay và đến giải pháp chức năng theo phong cách ngắn gọn này với O (n) thời gian chạy:

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; 
} 

Bạn cũng có thể có giải pháp một dòng tốt nếu bạn định nghĩa lớp tiện lợi này lần đầu tiên.NET framework, nhưng tôi đã không thể tìm thấy nó):

public static class Sequence 
{ 
    public static IEnumerable<T> Generate<T>(T seed, Func<T, T> next) 
    { 
     while (true) 
     { 
      yield return seed; 
      seed = next(seed); 
     } 
    } 
} 

Các giải pháp sau đó trở thành:

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(); 
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(); 
    } 
} 
1

Tương tự như các Func hai lót, bây giờ với chức năng địa phương nó có thể được thực hiện như thế này:

int Fibonacci(int i) => i <= 1 ? i : Fibonacci(i - 1) + Fibonacci(i - 2); 
Các vấn đề liên quan