Будет ли использование рекурсивного генератора стоить меньше памяти? - PullRequest
0 голосов
/ 17 ноября 2018

У меня есть пулы кортежей вроде [(0,0,27,4) (36,0,16,5) (14,36,14,8)], [......

Я бы сгенерировал кортежи кортежей из пулов кортежей по следующему правилу: суммирование каждого индекса не должно превышать или равняться пределу более 1 раза.

кортеж имеет длину 4, каждый его объект int. Допустим, у меня есть предельный кортеж (30,29,28,27) и пулы кортежей. Например, выбирая кортежи из пулов, по одному из каждого пула,

pool = [[(5,5,8,9),...],[(10,5,16,3),....],[(12,5,8,15),.....]]
selected =((5,5,8,9), (10,5,16,3), (12,5,8,15))

summing up each index,
5+10<30, 15+12<30 exceeding(or same as) limit 30 for 0 time ok
5+5<29, 10+5<29 exceeding limit 29 for 0 time ok
8+16<28, 24+8>28 exceeding limit 28 for 1 time ok (<2times)
9+3<12, 12+15=27 same as limit27 for 1 time ok

итак ((5,5,8,9), (10,5,16,3), (12,5,8,15)) будут получены.

но пример ((5,5,18,9), (10,5,10,3), (12,5,8,13)),

5+10<30, 15+12<30 exceeding(or same as) limit 30 for 0 time ok
5+5<29, 10+5<29 exceeding limit 29 for 0 time ok
18+10=28, 18+8 >28 exceeding limit 28 for 2 time False
9+3<12, 12+13<27 exceeding limit27 for 0 time ok

не будет уступлен.
Если я использую itertools.product, мне нужен дополнительный цикл для генерации кортежей. Но если я попытаюсь изменить данный код, он будет примерно равен 'itertools.product',

def product(*args):
    pools = [tuple(pool) for pool in args]
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]

и получение «результата» в последней строке стоит все время, потому что я делаю 6 кортежей, каждая длина которых равна 80.

поэтому я сгенерировал рекурсивный генератор,

def underlimit_product(*args, limit = (30,30,30,30), ncount = (0,0,0,0), exceed = 2, start = (0,0,0,0)):
    # (5,0,0,0),(0,5,0,0),(0,0,5,0),(0,0,0,5)
    pools = [tuple(pool) for pool in args]
    if max(ncount) >= exceed:
        raise StopIteration
    if not pools:
        raise StopIteration
    if len(pools) == 1:
        for y in pools[0]:
            if any([a+b>=c and d for a,b,c,d in zip(y,start,limit,ncount)]):
                if ncount:
                    continue
                else:
                    yield (y,)
            else:
                yield (y,)
        raise StopIteration
    else:
        for x in pools[0]:
            for y in pools[1]:
                count = [e+1 if b+c>=d else e for b,c,d,e in zip(x,start,limit,ncount)]
                if any(count):
                    n = underlimit_product(*pools[1:], ncount = count, exceed = exceed,limit = limit, start = [a+b for a,b in zip(x,start)])
                    for results in n:
                        yield (x,*results)
                else:
                    n = underlimit_product(*pools[1:], ncount = count, exceed = exceed,limit = limit, start = [a+b for a,b in zip(x,start)])
                    for results in n:
                        yield (x,*results)
    raise StopIteration

тест

pool = [[(5,5,8,9),(5,5,18,9)],[(10,5,16,3),(10,5,10,3)],[(12,5,8,15),(12,5,8,13)]]
b= list(underlimit_product(*pool, limit = (30,29,28,27)))
((5,5,8,9), (10,5,16,3), (12,5,8,15)) in b
True
((5,5,18,9), (10,5,10,3), (12,5,8,13)) in b
False
len(b)
16

Итак, я вижу лучший продукт ... может быть ..., он ослабит память моего компьютера? Будет ли это намного быстрее, чем использование itertools.product и проверка всех значений?

...