# -*- coding: utf-8 -*-
# q1001_answer_2.rb

# 工夫した点・苦労した点・感想等（ご自由にお書きください）：
# ・Enumerator#next と Integer#times を利用して、コンパクトにまとめました。

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

  def drop n
    return to_enum :drop, n unless block_given?
    enum = each
    n.times { enum.next }
    loop do
      yield enum.next
    end
  end
end

# ※これ以降は変更しないこと。
if $0 == __FILE__
  require 'test/unit'

  class AnswerQ1Test < Test::Unit::TestCase
    def setup
      @fib = AnswerQ1.new
    end

    def test_each
      expected = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
      result = []
      @fib.each do |n|
        result << n
        break if result.size == 10
      end
      assert_equal(expected, result)
    end

    def test_drop
      expected = [8, 13, 21, 34, 55]
      result = []
      @fib.drop(5) do |n|
        result << n
        break if result.size == 5
      end
      assert_equal(expected, result)
    end

    def test_100th_fib
      expected = 354_224_848_179_261_915_075
      result = @fib.drop(99).first
      assert_equal(expected, result)
    end
  end
end