• Source
    1. # -*- coding: utf-8 -*-
    2. # q1037_answer.rb
    3.  
    4. # 工夫した点・苦労した点・感想等(ご自由にお書きください):
    5. # ・infinite_product_process メソッドで得られる Enumerator オブジェクト(イテレータ)をキューに登録して順次実行する仕組みにしました。
    6. # ・infinite_product_process メソッドは、今までに列挙した値と、列挙に使わなかった残りの iters を引数にとって、
    7. #  そのうちの先頭のイテレータ(Enumerator オブジェクト)で値を列挙してその値と iters の残りを yield に引き渡しています。
    8.  
    9. # 必要に応じてここに require 文を挿入してもOKです(標準添付ライブラリに限る)。
    10. # 例:require set
    11.  
    12. # 無限リスト(ストリーム)に対応した直積(Cartesian product)を生成して列挙するメソッド
    13. def infinite_product *iters
    14. return to_enum :infinite_product, *iters unless block_given?
    15. q = [infinite_product_process([], iters)]
    16. until q.empty?
    17. it = q.shift
    18. begin
    19. vals, next_iters = it.next
    20. if next_iters.empty?
    21. yield vals
    22. else
    23. q << infinite_product_process(vals, next_iters)
    24. end
    25. q << it
    26. rescue StopIteration
    27. # pass
    28. end
    29. end
    30. end
    31.  
    32. def infinite_product_process vals, iters
    33. # メソッドの引数は変更しても可↑。ただし「ブロック引数 (&block)」は利用不可。
    34. # メソッドの引数を変更した場合は、下記の ↓ to_enum の引数も適切に変更すること。
    35. return to_enum :infinite_product_process, vals, iters unless block_given?
    36. if iters.empty?
    37. yield [vals, []]
    38. return
    39. end
    40. xs = iters.dup
    41. it = xs.shift #.dup.to_enum
    42. it.each do |e|
    43. yield [vals + [e], xs]
    44. end
    45. end
    46.  
    47. # ※これ以降は変更しないこと。
    48. if $0 == __FILE__
    49. require 'test/unit'
    50. require 'prime'
    51.  
    52. # 素数を列挙する Enumerator を返すメソッド
    53. def primes
    54. Prime.to_enum
    55. end
    56.  
    57. # 整数(>0)を列挙する Enumerable(≠Enumerator) を返すメソッド
    58. def nats
    59. (1..1.0/0)
    60. end
    61.  
    62. # フィボナッチ数列を列挙するメソッド
    63. def fib
    64. return to_enum :fib unless block_given?
    65. a, b = 0, 1
    66. loop do
    67. yield b
    68. a, b = b, a + b
    69. end
    70. end
    71.  
    72. # infinite_product メソッドのテストクラス
    73. class AnswerQ3Test < Test::Unit::TestCase
    74. # fib のみのテスト
    75. def test_fib_only
    76. expected = [[1], [1], [2], [3], [5], [8], [13], [21], [34], [55]]
    77. result = infinite_product(fib).take(10)
    78. assert_equal(expected, result)
    79. end
    80.  
    81. # nats と fib の infinite_product のテスト
    82. def test_product_nats_fib
    83. expected = [
    84. [1, 1],
    85. [1, 1], [2, 1],
    86. [1, 2], [2, 1], [3, 1],
    87. [1, 3], [2, 2], [3, 1], [4, 1],
    88. [1, 5], [2, 3], [3, 2], [4, 1], [5, 1],
    89. [1, 8], [2, 5], [3, 3], [4, 2], [5, 1], [6, 1]
    90. ]
    91. result = infinite_product(nats, fib).take(21)
    92. assert_equal(expected, result)
    93. end
    94.  
    95. # primes と nats と fib の infinite_product のテスト
    96. def test_product_primes_nats_fib
    97. expected = [
    98. [2, 1, 1],
    99. [2, 1, 1], [2, 2, 1],
    100. [3, 1, 1],
    101. [2, 1, 2], [2, 2, 1], [2, 3, 1],
    102. [3, 1, 1], [3, 2, 1],
    103. [5, 1, 1],
    104. [2, 1, 3], [2, 2, 2], [2, 3, 1], [2, 4, 1],
    105. [3, 1, 2], [3, 2, 1], [3, 3, 1],
    106. [5, 1, 1], [5, 2, 1],
    107. [7, 1, 1],
    108. [2, 1, 5], [2, 2, 3], [2, 3, 2], [2, 4, 1], [2, 5, 1],
    109. [3, 1, 3], [3, 2, 2], [3, 3, 1], [3, 4, 1],
    110. [5, 1, 2], [5, 2, 1], [5, 3, 1],
    111. [7, 1, 1], [7, 2, 1],
    112. [11, 1, 1]
    113. ]
    114. result = infinite_product(primes, nats, fib).take(35)
    115. assert_equal(expected, result)
    116. end
    117.  
    118. # nats と [1, 2, 3] の infinite_product のテスト
    119. def test_product_nats_1_3
    120. expected = [
    121. [1, 1],
    122. [1, 2], [2, 1],
    123. [1, 3], [2, 2], [3, 1],
    124. [2, 3], [3, 2], [4, 1],
    125. [3, 3], [4, 2], [5, 1],
    126. [4, 3], [5, 2], [6, 1]
    127. ]
    128. result = infinite_product(nats, 1..3).take(15)
    129. assert_equal(expected, result)
    130. end
    131.  
    132. # [1, 2, 3] と nats の infinite_product のテスト
    133. def test_product_1_3_nats
    134. expected = [
    135. [1, 1],
    136. [1, 2], [2, 1],
    137. [1, 3], [2, 2], [3, 1],
    138. [1, 4], [2, 3], [3, 2],
    139. [1, 5], [2, 4], [3, 3],
    140. [1, 6], [2, 5], [3, 4]
    141. ]
    142. result = infinite_product(1..3, nats).take(15)
    143. assert_equal(expected, result)
    144. end
    145.  
    146. def test_product_1_2_x3
    147. expected = [
    148. [1, 1, 1],
    149. [1, 1, 2], [1, 2, 1], [2, 1, 1],
    150. [1, 2, 2], [2, 1, 2], [2, 2, 1],
    151. [2, 2, 2]
    152. ]
    153. # result = infinite_product([1, 2], [1, 2], [1, 2]).take(9)
    154. result = infinite_product([1, 2], [1, 2], [1, 2]).to_a
    155. assert_equal(expected, result)
    156. end
    157.  
    158. def test_product_1_2_x4
    159. expected = [
    160. [1, 1, 1, 1],
    161. [1, 1, 1, 2], [1, 1, 2, 1], [1, 2, 1, 1], [2, 1, 1, 1],
    162. [1, 1, 2, 2], [1, 2, 1, 2], [1, 2, 2, 1], [2, 1, 1, 2], [2, 1, 2, 1], [2, 2, 1, 1],
    163. [1, 2, 2, 2], [2, 1, 2, 2], [2, 2, 1, 2], [2, 2, 2, 1],
    164. [2, 2, 2, 2]
    165. ]
    166. # result = infinite_product([1, 2], [1, 2], [1, 2], [1, 2]).take(16)
    167. result = infinite_product([1, 2], [1, 2], [1, 2], [1, 2]).to_a
    168. assert_equal(expected, result)
    169. end
    170. end
    171. end