У меня есть пулы кортежей вроде [(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 и проверка всех значений?