Python 一组玩家所有可能的牌/扑克组合
我正在寻找一个优雅(快速)的python函数,它可以生成以下两个数组的所有组合Python 一组玩家所有可能的牌/扑克组合,python,combinations,permutation,poker,playing-cards,Python,Combinations,Permutation,Poker,Playing Cards,我正在寻找一个优雅(快速)的python函数,它可以生成以下两个数组的所有组合 cards = ["8H", "8S", "8C", "8D", "9H", "9S", "9C", "9D", "10H", "10S", "10C", "10D", "AH", "AS", "AC", "AD"] players = ["_1", "_1", "_1", "_2", "_2", "_2", "_3", "_3", "_3", "_4", "_4", "_4", "_To", "_To", "_To
cards = ["8H", "8S", "8C", "8D", "9H", "9S", "9C", "9D", "10H", "10S", "10C", "10D", "AH", "AS", "AC", "AD"]
players = ["_1", "_1", "_1", "_2", "_2", "_2", "_3", "_3", "_3", "_4", "_4", "_4", "_To", "_To", "_To", "_Tc"]
组合如下:
[('8H', '_1'), ('8S', '_1'), ('8C', '_1'), ('8D', '_2'), ('9H', '_2'), ('9S', '_2'), ('9C', '_3'), ('9D', '_3'), ('10H', '_3'), ('10S', '_4'), ('10C', '_4'), ('10D', '_4'), ('AH', '_To'), ('AS', '_To'), ('AC', '_To'), ('AD', '_Tc')]
但是!没有平等,这就是我的意思。
例如:
如果卡片是:
["a", "b", "c", "d"]
["1", "1", "2", "2"]
如果玩家愿意:
["a", "b", "c", "d"]
["1", "1", "2", "2"]
结果:
[1a, 1b, 2c, 2d]
[1a, 1c, 2b, 2d]
[1a, 1d, 2b, 2c]
[1b, 1c, 2a, 2d]
[1b, 1d, 2a, 2c]
[1c, 1d, 2a, 2b]
例如:
[1a, 1b, 2d, 2c]
玩家2的(c和d)等于(d和c)
我尝试了itertools
的功能,比如组合
和排列
,但运气不佳。由于状态空间爆炸,在拥有所有组合后拒绝等于实际上不是一个选项
我希望有人能找到解决方案,因为谷歌搜索这个特定问题失败了。好的,那么你真正想要的是:
set(tuple(zip(p, players)) for p in it.permutations(cards))
但这需要花费太多的时间。让我们试试看
cards = set(["8H", "8S", "8C", "8D", "9H", "9S", "9C", "9D", "10H", "10S", "10C", "10D", "AH", "AS", "AC", "AD"])
def deals(cards, players, cards_per_player):
if not cards:
yield []
return
for hand in it.combinations(cards, cards_per_player[0]):
hand = set(hand)
for deal in deals(cards - hand, players[1:], cards_per_player[1:]):
yield zip([players[0]]*len(hand), hand) + deal
> for deal in deals(cards, ['_1', '_2', '_3', '_4', '_Tc', '_To'], [3,3,3,3,1,3]):
print deal
这仍然需要很长的时间,但处理卡片的方法很多。我建议使用递归算法 我使用生成器使代码在恒定的空间中运行,并尽快开始生成结果,而不是在最后生成巨大的结果;看看你以前是否听说过发电机 作为补充说明,我建议使用规范化的数据结构来保存玩家列表和手牌大小,这样就根本不需要使用
groupby
行了。。。在任何情况下,通常最好在默认情况下/大多数情况下保持数据的规范化,并且只使用非规范化/扁平化形式,例如,对于某些可能需要或使用扁平结构运行得更快的算法
这是代码;请随意提出清理/简化建议:
from itertools import combinations, groupby, islice
cards = ["a", "b", "c", "d"]
players = ["1", "1", "2", "2"]
def hand_combinations(players, cards):
# convert ["1", "1", "2", "2"] into [("1", 2), ("2", 2)]
players = list((x, len(list(y))) for x, y in groupby(players))
# sets are faster to operate on in our case
cards = set(cards)
def generate(players, cards):
if not players:
yield []
else:
# pick the first player
player_name, player_hand_size = players[0]
# and then walk over all the possible hands for this player
for player_hand in combinations(cards, player_hand_size):
# for each hand, use the cards that are left to build all the
# possible hands for the rest of the players in this iteration
for tail in generate(players[1:], cards - set(player_hand)):
yield [(player_name, player_hand)] + tail
return generate(players, cards)
# take only the 100 first combinations; otherwise it'll take
# forever with the larger example
combos = islice(hand_combinations(players, cards), 0, 100)
# convert back to the flat structure
flattened = [
' '.join(
player_name + ':' + card
for player_name, player_cards in combo
for card in player_cards
)
for combo in combos
]
from pprint import pprint
pprint(flattened)
输出:
['1:a 1:c 2:b 2:d',
'1:a 1:b 2:c 2:d',
'1:a 1:d 2:c 2:b',
'1:c 1:b 2:a 2:d',
'1:c 1:d 2:a 2:b',
'1:b 1:d 2:a 2:c']
或使用较大的可测试性:
['_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:8D _To:AH _To:9S _To:10D _Tc:8S',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:8D _To:AH _To:9S _To:8S _Tc:10D',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:8D _To:AH _To:10D _To:8S _Tc:9S',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:8D _To:9S _To:10D _To:8S _Tc:AH',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:10D _To:AH _To:9S _To:8D _Tc:8S',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:10D _To:AH _To:9S _To:8S _Tc:8D',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:10D _To:AH _To:8D _To:8S _Tc:9S',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:10D _To:9S _To:8D _To:8S _Tc:AH',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:AH _To:8S _To:9S _To:10D _Tc:8D',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:AH _To:8S _To:9S _To:8D _Tc:10D',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:AH _To:8S _To:10D _To:8D _Tc:9S',
'_1:AS _1:9H _1:8H _2:AC _2:10H _2:AD _3:10S _3:10C _3:9C _4:8C _4:9D _4:AH _To:9S _To:10D _To:8D _Tc:8S',
...
你可以每人使用一组卡片,并将卡片按顺序排列,因此当你匹配这两组卡片时,它们将是相同的。 您可以为每张卡使用一个元组(大小为2),其中第一个元素可以表示范围(13)中的值,第二个元素是颜色(也可以用范围(4)中的数字表示)。你可以很容易地用双for循环生成牌组,可能是一个字典,在发牌后,你可以删除你已经使用过的牌,这样就不会有重复的牌,当你发完所有的牌时(如果你有代码,很容易修改它以拥有不同数量的玩家),你可以点牌,将其与您已有的数据库进行比较,如果存在匹配项,则不保存该数据库。如果您愿意,您还可以保存该组的其余部分,以便进行一些统计,这样您就可以对每种情况进行所有可能的处理,这将是一个巨大的数据库。这样,你将拥有所有的可能性,没有重复的手或手的球员。(一号玩家与二号玩家在不同的交易中进行交易,反之亦然) 我希望这对你或其他人有帮助。 我不会给出代码示例,因为这个问题更像是一个如何解决这个问题的问题,其他人给了你一些编码技巧。即使您刚刚开始使用python,并且到目前为止只做了一些教程,也可以使用这种方法。
祝你好运;) 这只会导致一个组合,我需要所有组合。就像abcd例子一样。现在查看产品功能。@user3411641好的,我明白你的意思了。更新。我已经使标题和标签对这个问题更加合适和相关;上一个标题不是人们将要搜索这个特定(与扑克相关)问题的东西。“space”和“state”标记是在没有注意它们的含义的情况下选择的。@user3411641:也许我遗漏了一些东西,但我真的看不出在哪里可以优化任何东西。。。如果您不急于求值,则代码应在常量空间中运行,并在启动后立即发出结果。好吧,更重要的是,如果您正确使用返回值(即惰性地使用),则上述代码不会溢出/填充内存。@user3411641:如果您正确使用返回值,则上述代码不会溢出/填充内存。有关如何充分利用生成器/惰性的更多信息,请参阅提供的有关生成器的链接。