JaeJun LEE
JaeJun LEE

Reputation: 1334

generate two sets of combination with one list in python

Let's say there are 9 different cards and 2 different players. When 3 cards are given for each player (a total of 6 cards) out of 9 cards.

How can I generate all combinations of distributing 6 cards to 2 players?

The number of combinations is easily calculated:

number_of_combinations = (9!/(6!*3!)) * (6!/(3!*3!)) = 1680

Therefore, all combinations of distributing 6 cards to 2 players is (9!/(6!*3!)) * (6!/(3!*3!).

But generating combinations looks very difficult; this is what I have tried:

comb = itertools.combination([1,2,3,4,5,6,7,8,9], 6)

But there is one problem:

Let's say there are two lists, case1 and case2.

case1 = [1,2,3 ,4,5,6]
case2 = [1,2,4 ,3,5,6]

In my case, I have to handle case1 and case2 differently.

But if I just generate 6 size combinations, I can't do that.

Upvotes: 2

Views: 892

Answers (4)

Martijn Pieters
Martijn Pieters

Reputation: 1121774

To produce one dealing, you'd use the random.sample() function to pick 6 cards at random; give the first 3 to player 1, the remainder to player 2:

dealt_cards = random.sample(deck_of_cards, 6)
player1_hand, player2_hand = dealt_cards[:3], dealt_cards[3:]

To produce all possible combinations then, you'd use itertools.combinations() with size 6; but you still need to find all possible permutations of dividing those 6 cards over 2 hands that are unique:

for dealt_cards in itertools.combinations(deck_of_cards, 6):
    for hand1 in itertools.combinations(dealt_cards, 3):
        hand2 = tuple(card for card in dealt_cards if card not in hand1)

so from each dealt combination of 6 cards, all combinations of 3 cards are given to one player, leaving the remaining 3 cards for the other player.

This produces the expected number of solutions:

>>> from itertools import combinations
>>> deck = range(9)
>>> sum(1 for dealt in combinations(deck, 6) for _ in combinations(dealt, 3))
1680

and demo:

>>> for dealt_cards in combinations(deck, 6):
...     for hand1 in combinations(dealt_cards, 3):
...         hand2 = tuple(card for card in dealt_cards if card not in hand1)
...         print hand1, hand2
... 
(0, 1, 2) (3, 4, 5)
(0, 1, 3) (2, 4, 5)
(0, 1, 4) (2, 3, 5)
(0, 1, 5) (2, 3, 4)
(0, 2, 3) (1, 4, 5)
# ...
(4, 6, 7) (3, 5, 8)
(4, 6, 8) (3, 5, 7)
(4, 7, 8) (3, 5, 6)
(5, 6, 7) (3, 4, 8)
(5, 6, 8) (3, 4, 7)
(5, 7, 8) (3, 4, 6)
(6, 7, 8) (3, 4, 5)

You could also produce just the player 1 hands, then continue with the remainder of the deck to produce the player 2 hands:

for hand1 in itertools.combinations(deck_of_cards, 3):
    for hand2 in itertools.combinations([c for c in deck_of_cards if c not in hand1], 3):
        # ...

with the same expected count output and results:

>>> sum(1 for dealt in combinations(deck, 3) for _ in combinations([c for c in deck if c not in dealt], 3))
1680
>>> for hand1 in combinations(deck, 3):
...     for hand2 in combinations([c for c in deck if c not in hand1], 3):
...         print hand1, hand2
... 
(0, 1, 2) (3, 4, 5)
(0, 1, 2) (3, 4, 6)
(0, 1, 2) (3, 4, 7)
(0, 1, 2) (3, 4, 8)
(0, 1, 2) (3, 5, 6)
# ...
(6, 7, 8) (1, 3, 4)
(6, 7, 8) (1, 3, 5)
(6, 7, 8) (1, 4, 5)
(6, 7, 8) (2, 3, 4)
(6, 7, 8) (2, 3, 5)
(6, 7, 8) (2, 4, 5)
(6, 7, 8) (3, 4, 5)

albeit in a different order now.

Upvotes: 4

Carson Crane
Carson Crane

Reputation: 1217

combinations = itertools.combinations(cards, 6)

This would give you 6 chosen cards, then you need to distribute those 6 cards amongst the 2 players, so:

possibilities = []
for combination in combinations:
    hands = []
    hand1 = itertools.combinations(combination, 3)
    hands.append(hand1)#Hand1
    hands.append([x for x in combination if x not in hand1])#Hand2
    possibilities.append(hands)

This will generate a list possibilities for where each item is a list of the 2 different hands.

Upvotes: 1

L3viathan
L3viathan

Reputation: 27283

Just getting all possible combinations of 6 cards won't cut it, since the order in a single player's hand doesn't matter, but it matters who has which cards.

So for all combinations of 3 cards out of 9, choose 3 other cards out of the remaining 6:

from itertools import combinations

def getCardCombinations(cards):
    cards = set(cards)
    for first in combinations(cards, 3):
        for second in combinations(cards - set(first), 3):
            yield first, second

cards = [1,2,3,4,5,6,7,8,9]

all_combinations = getCardCombinations(cards)

Upvotes: -1

a p
a p

Reputation: 3198

If I understand you right, you want to get every possible combination of choosing 6 out of 9. Since the order doesn't really matter (we can treat the first 3 as player 1's and the second batch of 3 as player 2's hand), we can just use itertools.combinations:

from itertools import combinations, izip
hands = combinations(cards, 6)

Am I understanding your question right?

edit: to divide these into two hands of 3 each, you'd use:

player1, player2 = izip(*map(lambda x: (x[:3], x[3:]), combinations(cards, 6)))

Upvotes: -2

Related Questions