Tales of Verifier

テストエンジニアが自分の将来に不具合が起こらないことを確かめ合うRPG

rubyでテスト駆動ProjectEuler:Problem2

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, ...

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


さて、テストコード

require 'test/unit'
require './euler2.rb'

class Euler2 < Test::Unit::TestCase
  def test_euler2
    assert_equal(euler2(10), 10)
  end
end

テストコードの書き方もちゃんと知らないとだけど、とりあえずはrubyに慣れるのが目的

遅くて読みにくいコード

def fib(n)
  ans = 0
    if n == 1
      ans = 1
    elsif n == 2
      ans = 2
    else
      ans = fib(n-1) + fib(n-2)
    end
  return ans
end

def even(num)
  if num % 2 == 0
    return num
  else
    return 0
  end
end

def euler2(num)
  sum = 2
  i = 3
  b = fib(i)
  while b < num do
    i = i + 1
    sum = sum + even(b)
    b = fib(i)
  end
  return sum
end

”りふぁくたりんぐ”をしてみる。

疑問符演算子を使う

evenの中身を書き換える。

  if num % 2 == 0
    return num
  else
    return 0
  end

の部分を

 return (num % 2 == 0) ? num : 0

に変える。

同じ要領で、fibのほうも書き換えられる。

変更後その1

def fib(n)
  return (n <= 2) ? n : (fib(n-1) + fib(n-2))
end

def even(num)
  return (num % 2 == 0) ? num : 0
end

def euler2(num)
  sum = 2
  i = 3
  b = fib(i)
  while b < num do
    i = i + 1
    sum = sum + even(b)
    b = fib(i)
  end
  return sum
end
even?メソッドを使う

そもそも自前で作る必要なんてないよね、ということで、even?メソッドを使う。

変更後その2

def fib(n)
  return (n <= 2) ? n : (fib(n-1) + fib(n-2))
end

def euler2(num)
  sum = 2
  i = 3
  b = fib(i)
  while b < num do
    i = i + 1
    sum = (b.even?) ? (sum + b) : sum
    b = fib(i)
  end
  return sum
end

あとは末尾再帰に

見た目はすっきりしてきたので、あとは末尾再帰化を・・・というつもりだっt.あ
ところが、既に大分丁寧に解説されている記事を見つけてしまったので、
書かなくてもいいかな、と思っちゃいました。
ありがたく、こちらを見ましょう。
フィボナッチ数(2) ver.末尾再帰 - 名古屋で数学するプログラマ(仮)