Ibonacci sequence problem

Hello,

I have this problem.

By considering the terms in the Fibonacci sequence whose values do not
exceed four million, find the sum of the even-valued terms.

So i was thinking of solving it this way

1) n = Array.new [1,2]

2) while n[-1] + n[-2] < 4000000 do
    n << n[-2] + n[-1]
end

So I have now all the numbers.

3) n.inject { |sum, number| if number%2 == 0 then sum + number else sum end}

I see a answer but according to the site it's wrong.

Can anyone tell me where I'm thinking wrong ?

Roelof

I got 4_613_732 using

z, s = [0, 1], 0

while (z << (n = z[-1] + z[-2]))[-1] < 4_000_000
s += n if n % 2 == 0
end
p s

=> 4613732

What did they say you should get?

···

--
Posted via http://www.ruby-forum.com/.

Hi,

Roelof Wobben wrote in post #1077938:

By considering the terms in the Fibonacci sequence whose values do not
exceed four million, find the sum of the even-valued terms.

The problem is that you (unintentionally) start the sum with 1 instead
of 0. When you don't set a start value for inject, the aggregate value
is set to the first element. In this case it's 1, so the result will be
1 too big.

Also your code is rather "naive" in the sense that you're treating the
numbers as if they were physical objects and actually need to be
collected. This is very inefficient and completely unnessary. You only
need to track the last two numbers.

You should also get rid of some habits you seem to have adopted from
other programming languages (like Java or so). Things like "Array.new
[1,2]" and "number % 2 == 0" are useless in Ruby. The literal "[1,2]"
already *is* an array. And checking if an integer is even can be done by
simply calling "even?".

A low-level solution might look something like this:

previous, current =
  0, 1
sum = 0
while current <= 4_000_000
  sum += current if current.even?
  previous, current =
    current, previous + current
end
puts sum

A more high-level approach could consist of defining an Enumerator for
the fibonacci sequence and then apply "take_while", "select" and
"reduce" subsequently:

fibonacci = Enumerator.new do |yielder|
  previous, current =
    0, 1
  yielder << previous << current
  loop do
    previous, current =
      current, previous + current
    yielder << current
  end
end

sum = fibonacci.take_while{|e| e <= 4_000_000}.select(&:even?).reduce :+
puts sum

This actually works similar to your code, so it's not efficient. But
it's very readable and kind of "the Ruby way".

···

--
Posted via http://www.ruby-forum.com/\.

Thanks,

I think learning to programm is difficult without a sort of teacher. You never get checked if you are doing it the ruby way.
I'm now reading the Well Grounded Rubyist

But that one is without exercises so I can never check if I really understand it.
And the best way for me to learn something is to do it and not only to read about it.

Roelof

···

Date: Sat, 29 Sep 2012 10:48:58 +0900
From: lists@ruby-forum.com
Subject: Re: ibonacci sequence problem
To: ruby-talk@ruby-lang.org

Hi,

Roelof Wobben wrote in post #1077938:
> By considering the terms in the Fibonacci sequence whose values do not
> exceed four million, find the sum of the even-valued terms.

The problem is that you (unintentionally) start the sum with 1 instead
of 0. When you don't set a start value for inject, the aggregate value
is set to the first element. In this case it's 1, so the result will be
1 too big.

Also your code is rather "naive" in the sense that you're treating the
numbers as if they were physical objects and actually need to be
collected. This is very inefficient and completely unnessary. You only
need to track the last two numbers.

You should also get rid of some habits you seem to have adopted from
other programming languages (like Java or so). Things like "Array.new
[1,2]" and "number % 2 == 0" are useless in Ruby. The literal "[1,2]"
already *is* an array. And checking if an integer is even can be done by
simply calling "even?".

A low-level solution might look something like this:

previous, current =
  0, 1
sum = 0
while current <= 4_000_000
  sum += current if current.even?
  previous, current =
    current, previous + current
end
puts sum

A more high-level approach could consist of defining an Enumerator for
the fibonacci sequence and then apply "take_while", "select" and
"reduce" subsequently:

fibonacci = Enumerator.new do |yielder|
  previous, current =
    0, 1
  yielder << previous << current
  loop do
    previous, current =
      current, previous + current
    yielder << current
  end
end

sum = fibonacci.take_while{|e| e <= 4_000_000}.select(&:even?).reduce :+
puts sum

This actually works similar to your code, so it's not efficient. But
it's very readable and kind of "the Ruby way".

--
Posted via http://www.ruby-forum.com/\.

Roelof Wobben wrote in post #1077985:

And the best way for me to learn something is to do it and not only to
read about it.

Yes, absolutely! And I think my critique was a bit unjust: You've found
a valid, logical solution that works fine (apart from the small "inject"
mistake). So you've done a good job.

What I was talking about is the next step: improving the programming
style. When you've found a solution, it's always a good idea to try to
improve it and think about alternative approaches.

For example, you could ask yourself: Do I really need to save all
elements in an array? Or you could look for built-in Ruby methods to
solve the task: How can I create a "sequence object"? How can I select
all elements up to the first one that doesn't fulfill a condition? etc.

I've found this to very helpful in the learning process. Solving a
problem is one thing. Digging deep into the language to find a better
solution is even better.

···

--
Posted via http://www.ruby-forum.com/\.

Thanks I will try to do that.I have one question about it. Image I have this situation.Look for a number which is prime and can be divided by 2. I can do if number == prime and even?number then But as I see it if a number is not a prime there is no need to look if it's even.Then I could do if number == prime if even?number p number endend But this looks like a long code for the problem. What's the best ruby way to solve this ? Roelof

···

Date: Sat, 29 Sep 2012 20:18:41 +0900
From: lists@ruby-forum.com
Subject: Re: ibonacci sequence problem
To: ruby-talk@ruby-lang.org

Roelof Wobben wrote in post #1077985:
> And the best way for me to learn something is to do it and not only to
> read about it.

Yes, absolutely! And I think my critique was a bit unjust: You've found
a valid, logical solution that works fine (apart from the small "inject"
mistake). So you've done a good job.

What I was talking about is the next step: improving the programming
style. When you've found a solution, it's always a good idea to try to
improve it and think about alternative approaches.

For example, you could ask yourself: Do I really need to save all
elements in an array? Or you could look for built-in Ruby methods to
solve the task: How can I create a "sequence object"? How can I select
all elements up to the first one that doesn't fulfill a condition? etc.

I've found this to very helpful in the learning process. Solving a
problem is one thing. Digging deep into the language to find a better
solution is even better.

--
Posted via http://www.ruby-forum.com/\.

Roelof Wobben wrote in post #1078000:

Image I have
this situation.Look for a number which is prime and can be divided by 2.

Is this really the task? Because the only even prime number is 2
(obviously).

···

--
Posted via http://www.ruby-forum.com/\.

Date: Sat, 29 Sep 2012 21:18:16 +0900
From: lists@ruby-forum.com
Subject: Re: ibonacci sequence problem
To: ruby-talk@ruby-lang.org

Roelof Wobben wrote in post #1078000:
> Image I have
> this situation.Look for a number which is prime and can be divided by 2.

Is this really the task? Because the only even prime number is 2
(obviously).

--
Posted via http://www.ruby-forum.com/\.
No, It was a simplerer made task.The task is : What is the largest prime factor of the number 600851475143 So I can check if 600851475143 can be dived by a number ? 600851475143%^number == 0 if that not true im my opinion there is no need to look if the number is a prime. if that's true then I have to check if that number is a prime. I found on internet that I can check number.if_prime? Roelof