Maison  >  Article  >  développement back-end  >  Jeux d'index et de poker

Jeux d'index et de poker

Barbara Streisand
Barbara Streisandoriginal
2024-10-20 20:18:30952parcourir

Index and poker games

Défi hebdomadaire 291

Chaque semaine, Mohammad S. Anwar envoie The Weekly Challenge, une chance pour nous tous de trouver des solutions à deux tâches hebdomadaires. Mes solutions sont d'abord écrites en Python, puis converties en Perl. C'est une excellente façon pour nous tous de pratiquer le codage.

Défi, Mes solutions

Tâche 1 : Index intermédiaire

Tâches

Vous recevez un tableau d'entiers, @ints.

Écrivez un script pour trouver l'index du milieu (MI) le plus à gauche, c'est-à-dire le plus petit parmi tous les possibles.

Un index intermédiaire est un index où ints[0] ints[1] … ints[MI-1] == ints[MI 1] ints[MI 2] … ints[ints.length-1].

  • Si MI == 0, la somme du côté gauche est considérée comme étant égale à 0. De même,
  • si MI == ints.length - 1, la somme du côté droit est considérée comme étant 0.

Ma solution

C'est relativement simple. Je boucle la position de 0 à un de moins que la longueur des entrées. A chaque position je vois si la condition est remplie.

def middle_index(ints: list) -> int:
    for i in range(len(ints)):
        if sum(ints[:i]) == sum(ints[i + 1:]):
            # It is, so return this position
            return i

    return -1

Exemples

$ ./ch-1.py 2 3 -1 8 4
3

$ ./ch-1.py 1 -1 4
2

$ ./ch-1.py 2 5
-1

Tâche 2 : Classement des mains de poker

Tâche

Une main de poker à tirage se compose de 5 cartes, tirées d'un paquet de 52 : pas de jokers, pas de jokers. Un as peut être classé haut ou bas.

Écrivez un script pour déterminer les trois choses suivantes :

  1. Combien de mains différentes de 5 cartes peuvent être distribuées ?
  2. Combien de mains différentes de chacun des 10 rangs peuvent être distribuées ? Voir ici pour les descriptions des 10 rangs de mains de poker : https://en.wikipedia.org/wiki/List_of_poker_hands#Hand-ranking_categories
  3. Vérifiez les dix nombres que vous obtenez à l'étape 2 en les additionnant et en montrant qu'ils sont égaux au nombre que vous obtenez à l'étape 1.

Ma solution

Attachez-vous, car cela va être un long article. C'est aussi la première fois depuis longtemps qu'une tâche ne nécessite aucune intervention. Dans les défis que j'ai relevés, le dernier était le n°177.

Pour répondre à la première question, il existe 311 875 200 permutations possibles de cartes pouvant être distribuées (52 × 51 × 50 × 49 × 48). Toutefois, l’ordre des cartes n’a pas d’importance. Pour cinq cartes tirées, elles peuvent être disposées de 120 façons (5 × 4 × 3 × 2 × 1). Il existe donc 2 598 960 combinaisons uniques.

Je commence par créer un jeu de cartes. Pour cela j'ai un rang (numéro de carte) de 1 à 13. 1 est un as, 2 à 10 sont les chiffres, 11 est Valet, 12 est Reine et le Roi est 13. J'ai aussi une couleur s, c, d et h (de rechange, club, diamant et cœur respectivement). À l'aide d'une boucle double for, je génère les 52 cartes (un tuple de rang et de couleur) et les stocke dans une liste appelée deck.

Je parcoure ensuite chaque combinaison unique de cinq cartes du jeu et détermine quelle main je détiens. Enfin j'imprime les résultats.

def middle_index(ints: list) -> int:
    for i in range(len(ints)):
        if sum(ints[:i]) == sum(ints[i + 1:]):
            # It is, so return this position
            return i

    return -1

C'est la partie la plus facile :)

Pour la fonction get_hands, je commence par créer un dict de listes triées par rang (le numéro sur la carte) et par couleur (le symbole sur la carte). Je compte aussi la fréquence des rangs, car elle est souvent utilisée pour déterminer la main.

$ ./ch-1.py 2 3 -1 8 4
3

$ ./ch-1.py 1 -1 4
2

$ ./ch-1.py 2 5
-1

Donc pour les cartes 10s, 10h, 9d, 8h, 2d, ce qui suit serait réglé :

  • cards_by_rank {10 : ['s', 'h'], 9 : ['d'], 8 : ['h'], 2 : ['d']}
  • cards_by_suit {'s' : [10], 'h' : [10, 8], 'd' : [9, 2]}
  • count_by_rank {1 : 3, 2 : 1} (il y a trois rangs qui apparaissent une fois et un qui a deux cartes)

Il est alors temps de déterminer quelle main je tiens. Nous allons commencer par la quinte flush et la quinte flush. Ce sont les seules mains qui prennent en compte la couleur des cartes et que les cinq cartes sont de la même couleur. Ceci est déterminé lorsque le dict cards_by_suit n'a qu'une seule valeur.

Pour déterminer s'il s'agit d'une quinte flush, j'ordonne les cartes numériquement (de 1 à 13). Si la première carte est 1 (un as) et la dernière carte est 13 (roi), je retire la première carte et j'ajoute 14 à la fin de la liste. Cela permet à un 10, un Valet, une Dame, un Roi et un As d'être considérés comme une quinte flush. Une quinte flush se produit lorsque la différence entre le premier numéro de carte et la dernière carte est de quatre.

from collections import Counter, defaultdict
from itertools import combinations

def main():
    deck = [(rank, suit) for rank in range(1, 14) for suit in ('s', 'c', 'd', 'h')]
    hands = defaultdict(int)

    for cards in combinations(deck, 5):
        hand = get_hand(cards)
        hands[hand] += 1

    display_results(hands)

Pour le carré (quatre d'un même rang et une dernière carte aléatoire) et le full (trois d'un même rang, deux d'un rang différent), je peux utiliser le dict count_by_rank pour voir si la main correspond les critères spécifiés.

def get_hand(cards):
    cards_by_rank = defaultdict(list)
    cards_by_suit = defaultdict(list)

    for card in cards:
        number, suit = card
        cards_by_rank[number].append(card[1])
        cards_by_suit[suit].append(card[0])

    count_by_rank = Counter(len(cards_by_rank[r]) for r in cards_by_rank)

Pour déterminer si la main est droite, j'utilise une logique similaire à celle de la quinte flush. Je vérifie d'abord que j'ai cinq rangs uniques (numéros de carte), je les ordonne, je déplace l'as si nécessaire et je vérifie si la différence entre le haut et le bas est de 4.

    if len(cards_by_suit) == 1:
        cards = sorted(cards_by_rank)
        if cards[0] == 1 and cards[4] == 13:
            cards.pop(0)
            cards.append(14)

        if cards[4] - cards[0] == 4:
            return 'Straight flush'

        return 'Flush'

Brolan (trois cartes d'un même rang, deux cartes de rangs différents), deux paires (deux cartes d'un même rang, deux cartes d'un rang différent, dernière carte aléatoire), une paire (deux cartes d'un rang, trois cartes d'un rang différent chacune) peuvent toutes être calculées à l'aide du dict count_by_rank.

    if count_by_rank[4]:
        return 'Four of a kind'

    if count_by_rank[3] and count_by_rank[2]:
        return 'Full house'

Et enfin si rien ne correspond, retournez 'High card'. Vous ne voudrez certainement pas parier votre maison si vous détenez cette main :)

    if len(cards_by_rank) == 5:
        # Get the card ranks in the possible flush
        cards = sorted(cards_by_rank)
        if cards[0] == 1 and cards[4] == 13:
            cards.pop(0)
            cards.append(14)

        if cards[4] - cards[0] == 4:
            return 'Straight'

La fonction display_results affiche simplement les résultats (classés par classement) dans une présentation uniforme. Comme mentionné au début, pour chaque combinaison, il existe 120 permutations dans lesquelles la carte peut être commandée.

    if count_by_rank[3]:
        return 'Three of a kind'

    if count_by_rank[2] == 2:
        return 'Two pair'

    if count_by_rank[2]:
        return 'One pair'

Sortir

    return 'High card'

Cela a pris environ 15 secondes pour s'exécuter sur mon PC personnel.

Comme nous pouvons le voir sur la rangée du bas, nous avons 2 598 960 combinaisons et 311 875 200 permutations. Cela correspond à ce que nous nous attendions à voir dans le résultat.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn