user1230593
user1230593

Reputation: 243

Fibonacci sequence sum of even numbers

I ran across this problem here on stackoverflow:

"I'm having some trouble with this problem in Project Euler. Here's what the question asks: Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... Find the sum of all the even-valued terms in the sequence which do not exceed four million."

The top answer was this(which does not compile for me in VS2010...why?):

    IEnumerable<int> Fibonacci()
    {
        int n1 = 0;
        int n2 = 1;

        yield return 1;
        while (true)
        {
          int n = n1 + n2;
          n1 = n2;
          n2 = n;
          yield return n;
        }
    }

    long result=0;

    foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i % 2 == 0))
    {
        result+=i;
    }
    Console.WriteLine(result);

I decided to try it for myself before looking for an answer and came up with this(please tell me why or why not this is a good or bad way of solving this problem):

I wrote it in a class because I could add much more to the class in the future than just solving a single Fibonacci problem.

class Fibonacci
{
    private int prevNum1 = 1;
    private int prevNum2 = 2;
    private int sum = 0;

    public int GetSum(int min, int max)
    {
        prevNum1 = min;
        prevNum2 = prevNum1 + prevNum1;
        if (prevNum1 % 2 == 0)
        {
            sum += prevNum1;
        }
        if (prevNum2 % 2 == 0)
        {
            sum += prevNum2;
        }
        int fNum = 0;
        while (prevNum2 <= max)
        {
            fNum = prevNum1 + prevNum2;
            if (fNum % 2 == 0)
            {
                //is an even number...add to total
                sum += fNum;
            }
            prevNum1 = prevNum2;
            prevNum2 = fNum;

        }

        return sum;
    }

}

        Fibonacci Fib = new Fibonacci();
        int sum = Fib.GetSum(1, 4000000);

        Console.WriteLine("Sum of all even Fibonacci numbers 1-4,000,000 = {0}", sum);

Again, I'm looking for an answer as to why this is a good or bad way to solve this problem. Also why the first solution does not compile. I'm a beginning programmer and trying to learn. Thanks!

Upvotes: 2

Views: 3282

Answers (2)

Skepticism
Skepticism

Reputation: 46

The code doesn't compile because of this line:

foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i % 2 == 0))

First of all, .Where() is an extension method (google it) that can be called over a collection (like an IEnumerable of integers in this example). It returns another collection containing any elements that satisfy some condition.

Notice the argument to .Where() is an expression producing a boolean value, true or false..

i % 2 == 0

.Where() does not take a bool as an argument, in this case the appropriate argument is of the type

Func<int,bool>

Which basically means a function that has an int as argument and returns bool. You can define these quite simply

// defines a function taking an int, returning true if that int is even
Func<int,bool> foo = i => i % 2 == 0

So the correct way to use .Where() in this case would be

foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i => i % 2 == 0))

So you can see that .Where() takes the function we supply it and applies it to each number, returning a collection of numbers that are even.

There's some other magic happening with the yield keyword, feel free to google this, but it's more of an advanced topic.

Upvotes: 2

horgh
horgh

Reputation: 18534

With this it must compile:

foreach (int i in Fibonacci().TakeWhile(i => i < 4000000).Where(i => i % 2 == 0))
{
    result += i;
}

The problem why the code didn't compile was bad lambda expression, it was:

.Where(i % 2 == 0)

but must be

.Where(i => i % 2 == 0)

Upvotes: 3

Related Questions