Phinlodaさんの問題に答えてみる
とりあえず元のネタは以下
自分が中級者かどうかは微妙なところではあるが、Java と Python でやってみた。両方ともテストコード付き。
Java版
極々普通に実装。面白くもなんともない。最初は配列で書いたのだけど、テストで int の compare がちょっと面倒*1なことに気づいて 全部 List にしてしまった。
ついでに、テストコードでの結果の比較に文字列表現も利用してみたり。
参考:ObjectClub - JUnit 実践講座 - オブジェクトの文字列表現を活用しよう
import java.util.ArrayList; import java.util.List; public class Collect { public static List<List<Integer>> collect(List<Integer> source) { List<List<Integer>> result = new ArrayList<List<Integer>>(); int index = 0; int length = source.size(); while (index < length) { int n = source.get(index++); List<Integer> x = new ArrayList<Integer>(n); if (index + n > length) { break; } for (int i = 0; i < n; i++) { x.add(source.get(index + i)); } result.add(x); index += n; } return result; } }
import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.List; import org.junit.Test; public class CollectTest { @Test public void testCollect1() { List<Integer> source = Arrays.asList(1, 5, 3, 55, -45, 6, 2, 8, 7, 0, 1, 2); List<List<Integer>> expected = Arrays.asList( Arrays.asList(5), Arrays.asList(55, -45, 6), Arrays.asList(8, 7), Arrays.asList(new Integer[0]), Arrays.asList(2) ); List<List<Integer>> actual = Collect.collect(source); assertEquals(expected, actual); assertEquals("[[5], [55, -45, 6], [8, 7], [], [2]]", actual.toString()); } @Test public void testCollect2() { List<Integer> source = Arrays.asList(1, 2, 3, 4); List<List<Integer>> expected = Arrays.asList(Arrays.asList(2)); List<List<Integer>> actual = Collect.collect(source); assertEquals(expected, actual); assertEquals("[[2]]", actual); } }
Python版
generator で実装。値を取り出すところは iterator でやって、取り出す途中で StopIteration が送出されたらそこで停止と。
UnitTest に doctest を使ってみたけど、いいねこれ。テストコードが短い上にドキュメント=テストなもんだから、ドキュメントの不備も防げそう。
#!/usr/bin/env python def collect(array): """ >>> tuple(collect([1, 5, 3, 55, -45, 6, 2, 8, 7, 0, 1, 2])) ((5,), (55, -45, 6), (8, 7), (), (2,)) >>> tuple(collect([1, 2, 3, 4])) ((2,),) """ it = iter(array) while True: x = [] try: n = it.next() for i in xrange(n): x.append(it.next()) except StopIteration: return else: yield tuple(x) def _test(): import doctest doctest.testmod() if __name__ == '__main__': _test()
*1:といっても数行のコード追加でいいんだけど