более рубиновый способ сделать проект Euler # 2 - PullRequest
4 голосов
/ 12 июня 2010

Я пытаюсь изучить Ruby и прохожу некоторые проблемы с Project Euler.Я решил проблему номер два следующим образом:

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

Хотя это работает, кажется, это не очень рубиново - я не мог придумать ни одного хорошего чисто Ruby-ответа, как мог быс первым (puts (0..999).inject{ |sum, n| n%3==0||n%5==0 ? sum : sum+n }).

Ответы [ 9 ]

3 голосов
/ 12 июня 2010

Для хорошего решения, почему бы вам не создать генератор чисел Фибоначчи, как Prime или Triangular пример, который я дал здесь .

Из этого вы можетеиспользуйте хорошие Enumerable методы для решения проблемы.Возможно, вы захотите спросить, существует ли какой-либо шаблон для четных чисел Фибоначчи.

Отредактируйте свой вопрос, чтобы опубликовать свое решение ...

Примечание: существуют более эффективные способы, чем перечислять ихно они требуют больше математики, не будут столь же ясны, как это, и будут сиять, только если 4 миллиона были намного выше.

Поскольку demas 'опубликовал решение, вот исправленная версия:

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(:+)
2 голосов
/ 30 июля 2012
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
2 голосов
/ 22 марта 2011

Моя версия основана на ответе Марка-Андре Лафортуна:

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
1 голос
/ 20 мая 2014

Вот что я получил.Я действительно не вижу необходимости оборачивать это в классе.Вы могли бы, конечно, в более крупной программе, но в одном маленьком скрипте я обнаружил, что просто создаю дополнительные инструкции для переводчика.Вы можете выбрать четное, вместо отклонения нечетного, но это почти то же самое.

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(:+)
1 голос
/ 08 марта 2012
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 }
1 голос
/ 01 марта 2012

Вам не нужно return vals.last. Вы можете просто сделать vals.last, потому что Ruby вернет последнее выражение (я думаю, что это правильный термин) по умолчанию.

0 голосов
/ 23 июня 2016
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
0 голосов
/ 27 июля 2013

Я новичок в Ruby, но вот ответ, который я придумал.

 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}"
0 голосов
/ 13 июня 2010

Это мой подход. Я знаю, что это может быть меньше строк кода, но, может быть, вы можете взять что-то из этого.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...