Aaron Yodaiken
Aaron Yodaiken

Reputation: 19551

more ruby way of doing project euler #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 }).

Upvotes: 4

Views: 2155

Answers (9)

KellysOnTop23
KellysOnTop23

Reputation: 1435

def fib_nums(num)
    array = [1, 2]
    sum = 0
    until array[-2] > num
        array.push(array[-1] + array[-2])
    end
    array.each{|x| sum += x if x.even?}
    sum
end

Upvotes: 0

Marc-Andr&#233; Lafortune
Marc-Andr&#233; Lafortune

Reputation: 79562

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.

As demas' has posted a solution, here's a cleaned up version:

class Fibo
  class << self
    include Enumerable

    def each
      return to_enum unless block_given?
      a = 0; b = 1
      loop do
        a, b = b, a + b
        yield a
      end
    end
  end
end

puts Fibo.take_while { |i| i < 4000000 }.
          select(&:even?).
          inject(:+)

Upvotes: 3

tibbon
tibbon

Reputation: 1028

Here's what I got. I really don't see a need to wrap this in a class. You could in a larger program surely, but in a single small script I find that to just create additional instructions for the interpreter. You could select even, instead of rejecting odd but its pretty much the same thing.

fib = Enumerator.new do |y|
  a = b = 1
  loop do
    y << a
    a, b = b, a + b
  end
end

puts fib.take_while{|i| i < 4000000}
        .reject{|x| x.odd?}
        .inject(:+)

Upvotes: 1

user2624336
user2624336

Reputation:

I am new to Ruby, but here is the answer I came up with.

 x=1
 y=2
 array = [1,2]
 dar = [] 
   begin
     z = x + y

       if z % 2 == 0
         a = z
         dar << a
       end
     x = y
     y = z
     array << z
   end while z < 4000000
     dar.inject {:+}
     puts "#{dar.sum}"

Upvotes: 0

kgthegreat
kgthegreat

Reputation: 1322

def fib
  first, second, sum = 1,2,0
  while second < 4000000
    sum += second if second.even?
    first, second = second, first + second
  end
  puts sum
end

Upvotes: 2

user868386
user868386

Reputation: 411

fibs = [0,1]
begin
  fibs.push(fibs[-1]+fibs[-2])
end while not fibs[-1]+fibs[-2]>4000000
puts fibs.inject{ |sum, n| n%2==0 ? sum+n : sum }

Upvotes: 1

Andrew Grimm
Andrew Grimm

Reputation: 81520

You don't need return vals.last. You can just do vals.last, because Ruby will return the last expression (I think that's the correct term) by default.

Upvotes: 1

ceth
ceth

Reputation: 45295

My version based on Marc-André Lafortune's answer:

class Some
  @a = 1
  @b = 2

  class << self
    include Enumerable

    def each
      1.upto(Float::INFINITY) do |i|
        @a, @b = @b, @a + @b
        yield @b
      end
    end
  end
end

puts Some.take_while { |i| i < 4000000 }.select { |n| n%2 ==0 }
          .inject(0) { |sum, item| sum + item } + 2

Upvotes: 2

zed_0xff
zed_0xff

Reputation: 33217

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

Upvotes: 0

Related Questions