• Source
    1. # -*- coding: utf-8 -*-
    2. # q1011_answer_1.py
    3.  
    4. # 使用した Python のバージョン:
    5. # ・Python(Python 2.7.3)/Python3(Python 3.2.3)
    6. # 工夫した点・苦労した点・感想等(ご自由にお書きください):
    7. # ・collections.deque を利用して、要素の挿入・削除の効率化を図りました。
    8. # ・インスタンス変数 deques を導入し、オリジナルの it の生成結果と、それぞれのクローンの状態を保持するようにしました。
    9.  
    10. # 必要に応じてここに import 文を挿入してもOKです。
    11. # 例:import itertools
    12. from collections import deque
    13.  
    14. class IteratorCloner:
    15. def __init__(self, it):
    16. self._it = iter(it)
    17. self._deques = [deque()]
    18.  
    19. def get_clone(self):
    20. new_deque = deque(self._deques[0])
    21. self._deques.append(new_deque)
    22. while True:
    23. if not new_deque: # empty
    24. new_val = next(self._it)
    25. for d in self._deques:
    26. d.append(new_val)
    27. yield new_deque.popleft()
    28.  
    29. # ※これ以降は変更しないこと。
    30. if __name__ == '__main__':
    31. import unittest
    32. import random
    33. from itertools import islice, takewhile
    34.  
    35. def rand_enum():
    36. while True:
    37. # 1〜20の整数値をランダムに列挙
    38. yield random.randint(1, 20)
    39.  
    40. def fib():
    41. a, b = 0, 1
    42. while True:
    43. yield b
    44. a, b = b, a + b
    45.  
    46. def take_10(it):
    47. return list(islice(it, 10))
    48.  
    49. def take_under_100(it):
    50. return list(takewhile(lambda n: n < 100, it))
    51.  
    52. class IteratorClonerTest(unittest.TestCase):
    53. def setUp(self):
    54. self.cloner = IteratorCloner(fib())
    55.  
    56. def test_fib_clone1(self):
    57. fib = self.cloner.get_clone()
    58. expected = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    59. result = take_under_100(fib)
    60. self.assertEqual(result, expected)
    61.  
    62. def test_fib_clone2(self):
    63. fib1 = self.cloner.get_clone()
    64. fib2 = self.cloner.get_clone()
    65. expected = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    66. result1 = take_10(fib1) # dispose
    67. result2 = take_under_100(fib2)
    68. self.assertEqual(result2, expected)
    69.  
    70. def test_fib_cloneN(self):
    71. expected = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    72. result = None
    73. # 3回以上10回以下のランダム回数繰り返す
    74. for i in range(random.randint(3, 10)):
    75. result = take_under_100(self.cloner.get_clone())
    76. self.assertEqual(result, expected)
    77.  
    78. def test_rand_enum(self):
    79. cloner = IteratorCloner(rand_enum())
    80. expected = take_10(cloner.get_clone())
    81. result = take_10(cloner.get_clone())
    82. self.assertEqual(result, expected)
    83.  
    84. # run tests
    85. unittest.main()
    86.