Home > front end >  How do you create all possible combinations of size X, from multiple lists, pulling from each list i
How do you create all possible combinations of size X, from multiple lists, pulling from each list i

Time:01-14

I have 4 lists and I want to create all possible combinations of exactly 18 values in these lists. I need to pull from each list in order though, so I can't use itertools.combinations. Also each element in the list can only be used once. So there can't be two 'QB1' values in each output.

I also need to set a rule where certain lists need at least X values used.

Min usage by list:

qb: 1
rb: 2
wr: 3
te: 1

qb = ['QB1', 'QB2', 'QB3']
rb = ['RB1', 'RB2', 'RB3', 'RB4', 'RB5', 'RB6', 'RB7', 'RB8', 'RB9', 'RB10']
wr = ['WR1', 'WR2', 'WR3', 'WR4', 'WR5', 'WR6', 'WR7', 'WR8', 'WR9', 'WR10', 'WR11']
te = ['TE1', 'TE2', 'TE3', 'TE4', 'TE5']

Example Output:

['QB1', 'QB2', 'QB3', 'RB1', 'RB2', 'RB3', 'RB4', 'RB5', 'RB6', 'RB7', 'RB8', 'WR1', 'WR2', 'WR3', 'WR3', 'TE1', 'TE2', 'TE3']

Example of an output that we don't want:

['QB5', 'QB2', 'QB3', 'RB1', 'RB2', 'RB3', 'RB4', 'RB5', 'RB6', 'RB7', 'RB8', 'WR1', 'WR2', 'WR3', 'WR3', 'TE1', 'TE2', 'TE3']

In the bad example, QB5 was used before QB1/QB2/QB3/QB4. Each list needs to be used in order.

I tried using itertools.combinations, but that results in values at the end of the list being used in some combinations before the values at the beginning. Doing that many combinations would also break my computer.

CodePudding user response:

Your question is a bit vague but I think that I got the gist, something that does what you want, but with repetitions of items from the same list is:

import random

qb = ['QB1', 'QB2', 'QB3']
rb = ['RB1', 'RB2', 'RB3', 'RB4', 'RB5', 'RB6', 'RB7', 'RB8', 'RB9', 'RB10']
wr = ['WR1', 'WR2', 'WR3', 'WR4', 'WR5', 'WR6', 'WR7', 'WR8', 'WR9', 'WR10', 'WR11']
te = ['TE1', 'TE2', 'TE3', 'TE4', 'TE5']

lists = [qb, rb, wr, te]
combs = []
i = 0
while True:
    combs.append(random.choice(lists[i]))
    if random.random() > 0.9:
        i  = 1
    if i == len(lists) or len(combs) == 18:
        break
print(combs)

If repetitions from the same lists are to be avoided just add a check on the randomly chosen item if it has been chosen again.

Output:

['QB3', 'QB2', 'QB2', 'QB3', 'QB2', 'RB10', 'RB4', 'RB5', 'RB8', 'RB1', 'RB5', 'RB8', 'RB4', 'RB8', 'RB9', 'RB1', 'RB3', 'WR3']

CodePudding user response:

Here's a quick way to accomplish what you're looking for:

def binPack():

    inputs = [['QB1', 'QB2', 'QB3'],
              ['RB1', 'RB2', 'RB3', 'RB4', 'RB5', 'RB6', 'RB7', 'RB8', 'RB9', 'RB10'],
              ['WR1', 'WR2', 'WR3', 'WR4', 'WR5', 'WR6', 'WR7', 'WR8', 'WR9', 'WR10', 'WR11'],
              ['TE1', 'TE2', 'TE3', 'TE4', 'TE5']
              ]

    constraints = [1,2,3,1]
    total = 18

    minChoices = [itertools.combinations(L,c) for L,c in zip(inputs, constraints)]  # the minimum required selection from each list
    for minChoice in itertools.product(*minChoices):  # for each combination of minimal required choices
        remainders = [set(L) for L in inputs]  # the remaining choices from each list. We'll remove what we've already chosen
        for r,remainder in enumerate(remainders):
            for c in minChoice[r]:
                remainder.remove(c)

        remainders = sum([list(r) for r in remainders], start=[])  # all possible remaining choices to add to the answer
        for c in itertools.combinations(remainders, total-len(minChoice)):
            yield tuple(itertools.chain.from_iterable(minChoice))   c

Here's the first 10 outputs:

('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'WR8')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'WR4')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'WR9')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'WR10')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'WR11')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'TE5')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'TE4')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'TE3')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR6', 'TE2')
('QB1', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE1', 'QB2', 'QB3', 'RB8', 'RB9', 'RB6', 'RB5', 'RB3', 'RB7', 'RB4', 'RB10', 'WR7', 'WR5', 'WR8', 'WR4')
  • Related