All Possible Combinations Of Card/poker Hands For A Set Of Players
Solution 1:
I'd suggest using a recursive algorithm.
I'm using generators for the code to run in constant-space, as well as start producing results ASAP as opposed to a huge result at the end; see http://www.dabeaz.com/generators/ if you haven't heard of generators before.
As a side note, I'd suggest using a normalized data structure to hold your list of players and hand sizes to start with, so that the line with groupby
wouldn't be necessary at all... And in any case, it's generally a good idea to keep your data normalized by default/most of the time and only use denormalized/flattened forms for example for certain algorithms that might need or run faster with flat structures.
Here's the code; feel free to propose clean-ups/simplifications:
from itertools import combinations, groupby, islice
cards = ["a", "b", "c", "d"]
players = ["1", "1", "2", "2"]
defhand_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)
defgenerate(players, cards):
ifnot players:
yield []
else:
# pick the first player
player_name, player_hand_size = players[0]
# and then walk over all the possible hands for this playerfor 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 iterationfor 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)
Outputs:
['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']
or with the larger examople:
['_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',
...
Solution 2:
Okay, so what you actually want is:
set(tuple(zip(p, players)) for p in it.permutations(cards))
But that takes way too much time. So let's try.
cards = set(["8H", "8S", "8C", "8D", "9H", "9S", "9C", "9D", "10H", "10S", "10C", "10D", "AH", "AS", "AC", "AD"])
defdeals(cards, players, cards_per_player):
ifnot cards:
yield []
returnfor hand in it.combinations(cards, cards_per_player[0]):
hand = set(hand)
for deal in deals(cards - hand, players[1:], cards_per_player[1:]):
yieldzip([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
Which still takes a long time, but it's a lot of ways to deal the cards.
Solution 3:
You could use an array of cards per person, and put the cards in order, so when you match the two arrays, they will be the same. You could use a tuple(size 2) for each card, where the first element could represent the value in range(13), and the second element would be the color (also represented with a number in range(4) ). You can easily generate the deck with a double for loop, maybe as a dictionary and after dealing the cards, you can remove the ones that you already used, so there will be no duplicates, and when you dealt all the hands (if you have the code it will be easy to modify it to have different number of players) you can order the hands, compare it with the database that you already have, and don't save it if there is a match, also you can save the remainder of the deck, to do some statistics if you want, than you can have all the possible dealings for every situation, which will be a huge database regardless. This way you will have all possibilities, with no duplicates in the hands or within hands of players. (player one having the hand of player two in a different deal and vice versa) I hope this helped you, or someone else. I'm not giving code examples, because this question is more like a how to solve this problem, and the others gave you coding tips. Also this approach can be done even if you just started python and only did some tutorials until now. Good luck ;)
Post a Comment for "All Possible Combinations Of Card/poker Hands For A Set Of Players"