bebraw
9/24/2011 - 10:43 AM

Infinite list for python

Infinite list for python

from inf import InfList
from tests import pos_l, neg_l

def lazy_zip(a, b):
    if isinstance(a, InfList) and isinstance(b, InfList):
        return InfList([a[0], b[0]], [a[1], b[1]], lambda i, x, y: [a[i], b[i]])

    return old_zip(a, b);

old_zip = zip
zip = lazy_zip

zip_l = zip(pos_l, neg_l)
assert zip_l[0] == [1, -1]
assert zip_l[1] == [2, -2]

zip_hybrid = zip(pos_l, range(3, 5))
assert zip_hybrid == [(1, 3), (2, 4)]

def concat(a):
    # concat just zipped InfLists for now... might want to generalize
    return InfList(a[0][0], a[0][1], lambda i, x, y: a[i / 2][i % 2])

concat_l = concat(zip(pos_l, neg_l))
assert concat_l[0] == 1
assert concat_l[1] == -1
assert concat_l[2] == 2
assert concat_l[3] == -2
assert concat_l[4] == 3
assert concat_l[5] == -3

def lazy_map(f, a):
    if isinstance(a, InfList):
        return InfList(f(a[0]), f(a[1]), lambda i, x, y: f(a[i]))

    return old_map(f, a)

old_map = map
map = lazy_map

map_l = map(lambda a: a * 2, pos_l)
assert map_l[0] == 2
assert map_l[1] == 4

def lazy_filter(f, a):
    if isinstance(a, InfList):
        def valid():
            i = 0
            while True:
                if f(a[i]):
                    yield a[i]

                i += 1

        valids = valid()

        return InfList(valids.next(), valids.next(), lambda i, x, y: valids.next())

    return old_filter(f, a)

old_filter = filter
filter = lazy_filter

filter_l = filter(lambda a: a % 2, pos_l)
assert filter_l[0] == 1, filter_l[0]
assert filter_l[1] == 3, filter_l[1]
from inf import InfList

pos_l = InfList(1, 2)
assert pos_l[0] == 1
assert pos_l[1] == 2
assert pos_l[2] == 3
assert pos_l[3] == 4

neg_l = InfList(-1, -2)
assert neg_l[0] == -1
assert neg_l[1] == -2
assert neg_l[2] == -3
assert neg_l[3] == -4

fibo = InfList(0, 1, lambda i, a, b: a + b)
assert fibo[0] == 0
assert fibo[1] == 1
assert fibo[2] == 1
assert fibo[3] == 2
assert fibo[4] == 3

# slice
assert fibo[1:4] == [1, 1, 2]
class InfList(object):
    def __init__(self, *items):
        self._rule = (lambda i, a, b: 2 * b - a) if len(items) == 2 else items[2]
        self._items = list(items[0:2])

    def __getitem__(self, k):
        if k >= len(self._items):
            self._calc_items(k)

        return self._items[k]

    def _calc_items(self, limit):
        if isinstance(limit, slice):
            limit = limit.stop

        for i in xrange(len(self._items), limit + 1):
            new_val = self._rule(i, self[-2], self[-1])
            self._items.append(new_val)

    def __unicode__(self):
        self._calc_items(3)
        f0, f1, f2 = map(unicode, self._items[:3])
        return '[' + f0 + ', ' + f1 + ', ' + f2 + ', ..]'