views:

118

answers:

2

I'm trying to learn Ruby, and am going through some of the Project Euler problems. I solved problem number two as such:

def fib(n)
  return n if n < 2
  vals = [0, 1]
  n.times do
    vals.push(vals[-1]+vals[-2])
  end
  return vals.last
end
i = 1
s = 0
while((v = fib(i)) < 4_000_000)
  s+=v if v%2==0
  i+=1
end
puts s

While that works, it seems not very ruby-ish—I couldn't come up with any good purely Ruby answer like I could with the first one ( puts (0..999).inject{ |sum, n| n%3==0||n%5==0 ? sum : sum+n }).

+2  A: 

For a nice solution, why don't you create a Fibonacci number generator, like Prime or the Triangular example I gave here.

From this, you can use the nice Enumerable methods to handle the problem. You might want to wonder if there is any pattern to the even Fibonacci numbers too.

Edit your question to post your solution...

Note: there are more efficient ways than enumerating them, but they require more math, won't be as clear as this and would only shine if the 4 million was much higher.

Marc-André Lafortune
If you get stuck writing such a generator, have a look at the following: http://www.davidflanagan.com/2007/08/fibonacci-numbers-with-ruby-19-fibers.html
Michael Kohl
@Michael: oh my! That post is a _terrible_ use of `Fiber` and way too complex (let alone slow). If you need something like it, write a good enumerable (have a look at the triangular number generator I pointed to) and get an `Enumerator` and use `next`, but even that should be avoided.
Marc-André Lafortune
A: 

That's my approach. I know it can be less lines of code, but maybe you can take something from it.

class Fib
  def first
    @p0 = 0
    @p1 = 1
    1
  end
  def next
    r = 
      if @p1 == 1
        2
      else
        @p0 + @p1
      end
    @p0 = @p1
    @p1 = r
    r
  end
end

c = Fib.new
f = c.first
r = 0
while (f=c.next) < 4_000_000
  r += f if f%2==0
end
puts r
zed_0xff
If you start with `@p0 = 1`, you can get rid of your `if`... Also, Ruby has parallel assignment which can be useful here. Did you know that `2.even?` returns `true`?
Marc-André Lafortune
I know that. I just posted my archive code from my Project Euler tasks archive. I wrote this a long ago.
zed_0xff