def mrange(minvec, maxvec=None):  
    if maxvec is None:
        maxvec = minvec
        minvec = [0] * len(maxvec)
    vec = list(minvec)
    unitpos = len(vec) - 1
    maxunit = maxvec[unitpos]
    _tuple = tuple
    while 1:
        if vec[unitpos] == maxunit:
            i = unitpos
            while vec[i] == maxvec[i]:
                vec[i] = minvec[i]
                i -= 1
                if i == -1:
                    return            
                vec[i] += 1
        yield _tuple(vec)
        vec[unitpos] += 1

''' Clicker wheel objects:
  - init with a sqn
  - return init value
  - when called, repopulates vec, calls another clicker when rolling over
  - last one terminates
'''

from itertools import cycle

def odom(*args):
    ''' Cartesian product of input interables.  Equivalent to nested for-loops.
    For example, product(A, B) returns the same as ((x,y) for x in A for y in B).
    The leftmost iterators are in the outermost for-loop, so the output tuples
    cycle in a manner similar to an odometer (with the rightmost element changing
    on every iteration).

    product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)
    product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...
    '''    
    #itertools.cycle version with next() calls'
    _tuple = tuple 
    cycles = [cycle(p).next for p in args]
    vec = [c() for c in cycles]
    minvec = vec[:]
    i = right = len(vec) - 1
    while 1:
        yield _tuple(vec)
        vec[i] = cycles[i]()
        while vec[i] == minvec[i]:
            i -= 1
            if i == -1:
                return
            vec[i] = cycles[i]()
        else:
            i = right

        
def odom(*args):
    #Index version for easy conversion to C'
    ''' Cartesian product of input interables.  Equivalent to nested for-loops.
    For example, product(A, B) returns the same as ((x,y) for x in A for y in B).
    The leftmost iterators are in the outermost for-loop, so the output tuples
    cycle in a manner similar to an odometer (with the rightmost element changing
    on every iteration).

    product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)
    product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...
    '''    
    _tuple = tuple
    pools = map(list, args)
    maxvec = map(len, pools)
    indices = [0] * len(pools)
    vec = [p[0] for p in pools]
    i = right = len(pools) - 1
    slots = list(reversed(range(len(pools))))
    while 1:
        yield _tuple(vec)
        for i in slots:
            indices[i] += 1
            if indices[i] != maxvec[i]:
                vec[i] = pools[i][indices[i]]
                break
            indices[i] = 0
            vec[i] = pools[i][indices[i]]
        else:
            return


if __name__ == '__main__':
    for t in odom(range(2), range(3), 'abcd'):
        print t

    print list(odom('ab', range(3)))

    print list(odom(*[range(2)]*3))

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to