compact-number-list (3)

stepに対応するようにして、さらにイテレータ(無限リスト)に対応するように拡張してみた。

from itertools import izip

def count2(start, step=1):
    cnt = start
    while True:
        yield cnt
        cnt += step

def compact_number_list(seq):
    seq = iter(seq)
    curr, next_ = None, None
    while True:
        if not curr:
            try:
                curr = seq.next()
            except:
                break
        if not next_:
            try:
                next_ = seq.next()
            except:
                yield curr
                break
        c = count2(curr, next_-curr)
        c.next()
        c.next()
        has_step = False
        last = None
        for next2, cnt in izip(seq, c):
            if next2 == cnt:
                has_step = True
                last = next2
                continue
            else:
                if has_step:
                    if next_-curr == 1:
                        yield [curr, last]
                    else:
                        yield [curr, last, next_-curr]
                    curr, next_ = next2, None
                    break
                else:
                    yield curr
                    curr = next_
                    next_ = next2
                    break
        else:
             if has_step:
                 if next_-curr == 1:
                     yield [curr, last]
                 else:
                     yield [curr, last, next_-curr]
             else:
                 yield curr
                 yield next_
             break

print list(compact_number_list([1, 3, 4, 5, 6, 12, 13, 15, 20, 25, 26, 27]))  #=> [1, [3, 6], 12, 13, [15, 25, 5], 26, 27]

かなり汚すぎるので時間ができたら実装を書き直すつもり。あともう少しPythonの無限リストの扱いに関して研究するつもり。Pythonイテレータ(およびジェネレータ)はHaskellの遅延リスト(lazy list)の部分集合的な機能しかないと思うので、何が足りないかをあとで考える。