在 python 中用一个列表生成两组组合

generate two sets of combination with one list in python

假设有 9 张不同的牌和 2 个不同的玩家。当从 9 张牌中给每位玩家 3 张牌(共 6 张牌)时。

如何生成将 6 张牌分配给 2 个玩家的所有组合?

组合数很容易计算:

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

因此,将6张牌分给2人的所有组合为(9!/(6!*3!)) * (6!/(3!*3!)

但是生成组合看起来很困难;这是我试过的:

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

但是有一个问题:

假设有两个列表,case1 和 case2。

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

就我而言,我必须以不同方式处理 case1 和 case2。

但如果我只生成 6 种尺寸组合,我就做不到。

要产生一次发牌,您需要使用random.sample() function随机挑选6张牌;将前 3 个给玩家 1,其余的给玩家 2:

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

为了生成 所有 可能的组合,您将使用 itertools.combinations() 和大小 6;但您仍然需要找到将这 6 张牌分成 2 手牌的所有可能排列:

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)

因此,从每张 6 张牌的组合中,所有 3 张牌的组合都给了一个玩家,剩下的 3 张牌给了另一个玩家。

这产生了预期数量的解决方案:

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

和演示:

>>> 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)

您也可以只生成玩家 1 手牌,然后继续使用牌组的剩余部分生成玩家 2 手牌:

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):
        # ...

具有相同的预期计数输出和结果:

>>> 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)

虽然现在顺序不同了。

combinations = itertools.combinations(cards, 6)

这会给你 6 张选定的牌,然后你需要将这 6 张牌分配给 2 名玩家,所以:

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)

这将生成一个列表 possibilities,其中每个项目都是 2 只不同手的列表。

仅仅获得 6 张牌的所有可能组合并不能解决问题,因为单个玩家手中的顺序并不重要,但谁有哪些牌很重要。

因此对于 9 张牌中 3 张的所有组合,从剩余的 6 张牌中选择 3 张 other 张:

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)

如果我没理解错的话,你想获得从 9 中选择 6 的所有可能组合。因为顺序并不重要(我们可以将前 3 个视为玩家 1,将第二批 3 作为玩家 2 的手),我们可以只使用 itertools.combinations:

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

我理解你的问题了吗?

编辑:将这些分成两手,每手 3 个,您将使用:

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