Ce problème semble simple à première vue, mais il s'avère être beaucoup plus compliqué qu'il n'y paraît. Il me laisse perplexe pour le moment.
Il y a 52c5 = 2.598.960 façons de choisir 5 cartes dans un jeu de 52 cartes. Cependant, comme les couleurs sont interchangeables au poker, beaucoup d'entre elles sont équivalentes - la main 2H 2C 3H 3S 4D est équivalente à 2D 2S 3D 3C 4H - il suffit d'intervertir les couleurs. D'après wikipedia Il existe 134 459 mains de 5 cartes distinctes, si l'on tient compte de la possibilité de recolorations de couleurs.
La question est de savoir comment générer efficacement toutes ces mains possibles. Je ne veux pas générer toutes les mains, puis éliminer les doublons, car je veux appliquer le problème à un plus grand nombre de cartes, et le nombre de mains à évaluer devient rapidement incontrôlable. Mes tentatives actuelles se sont concentrées sur la génération en profondeur d'abord, et sur le suivi des cartes actuellement générées pour déterminer quelles couleurs et quels rangs sont valables pour la prochaine carte, ou sur la génération en largeur d'abord, en générant toutes les cartes suivantes possibles, puis en éliminant les doublons en convertissant chaque main en une version "canonique" par recoloration. Voici ma tentative de solution "breadth-first", en Python :
# A card is represented by an integer. The low 2 bits represent the suit, while
# the remainder represent the rank.
suits = 'CDHS'
ranks = '23456789TJQKA'
def make_canonical(hand):
suit_map = [None] * 4
next_suit = 0
for i in range(len(hand)):
suit = hand[i] & 3
if suit_map[suit] is None:
suit_map[suit] = next_suit
next_suit += 1
hand[i] = hand[i] & ~3 | suit_map[suit]
return hand
def expand_hand(hand, min_card):
used_map = 0
for card in hand:
used_map |= 1 << card
hands = set()
for card in range(min_card, 52):
if (1 << card) & used_map:
continue
new_hand = list(hand)
new_hand.append(card)
make_canonical(new_hand)
hands.add(tuple(new_hand))
return hands
def expand_hands(hands, num_cards):
for i in range(num_cards):
new_hands = set()
for j, hand in enumerate(hands):
min_card = hand[-1] + 1 if i > 0 else 0
new_hands.update(expand_hand(hand, min_card))
hands = new_hands
return hands
Malheureusement, cela génère trop de mains :
>>> len(expand_hands(set([()]), 5))
160537
Quelqu'un peut-il suggérer une meilleure façon de générer uniquement les mains distinctes, ou m'indiquer où je me suis trompé dans ma tentative ?
0 votes
Bonne question, à quoi sert-il ? si vous voulez l'utiliser pour calculer les chances d'une main par rapport à la seconde, vous pouvez utiliser la méthode monte-carlo.
0 votes
Je précalcule tous les matchs en tête-à-tête. Le Monte-Carlo est pour les gens qui n'ont pas assez de puissance de calcul ;)
0 votes
C'est un problème très intéressant. Je n'ai pas le temps d'y jouer pour le moment, mais j'ai eu quelques idées qui peuvent être utiles ou non. La première est de travailler de haut en bas, c'est-à-dire que le rang de chaque carte doit être inférieur ou égal à celui de la carte précédente (A-9-9-8-2, par exemple). Deuxièmement, je crois qu'il est possible de ne tirer qu'un trèfle comme première carte, un trèfle ou un carreau comme deuxième carte, et un non-spade comme troisième carte. (Je n'ai pas encore compris votre code bitwise, il est donc possible que vous fassiez déjà ces choses).
1 votes
Vous intéressez-vous aux classements significatifs des mains ou aux permutations réelles ? Par exemple, si vos deux premières cartes ne sont pas de la même couleur, alors vous n'avez aucune possibilité de faire une couleur, et vous pouvez ignorer les couleurs pour le reste de ce sous-arbre. Je pensais qu'il n'y avait que ~7500 mains de poker à classement unique via cactus Kev. Je vais voir si je peux trouver le lien.
0 votes
@davidchambers Vous avez raison de les générer par ordre de classement - c'est le moyen le plus simple d'éliminer les permutations de mains. L'ensemble des couleurs valides pour chaque nouvelle carte augmente comme vous le décrivez, sauf que l'ensemble valide dépend de toutes les cartes précédentes - par exemple, si les deux premières cartes étaient de la même couleur, il n'y a que deux possibilités pour la troisième. C'est de cette façon que j'ai travaillé initialement avec un DFS, mais j'ai quand même fini par générer des mains isomorphiques :/
0 votes
@NickLarsen Je ne me soucie pas des classements - juste des mains distinctes. Le classement est un problème distinct.
0 votes
Je n'ai jamais réussi à obtenir le bon numéro (134 459) après avoir consulté ce document et d'autres aides en ligne. Mais, en utilisant mon marteau de forgeron et ma tronçonneuse, j'ai réussi à produire l'énumération correcte. Je n'ai également jamais trouvé de liste par type de main, donc je la partage ici.4Kind, 156 FH, 312 3K, 4290 2P, 6864 1P, 57200 SF, 9 ST, 500 FL, 1277 HighCard, 63850 RF, 1 Total 134459