ホームページ >バックエンド開発 >Python チュートリアル >インデックスとポーカー ゲーム

インデックスとポーカー ゲーム

Barbara Streisand
Barbara Streisandオリジナル
2024-10-20 20:18:301079ブラウズ

Index and poker games

ウィークリーチャレンジ 291

Mohammad S. Anwar は毎週、毎週 2 つのタスクに対する解決策を全員が考え出すチャンスであるウィークリー チャレンジを送信します。私のソリューションは最初に Python で書かれ、次に Perl に変換されます。これは、私たち全員がコーディングを練習するのに最適な方法です。

挑戦、私の解決策

タスク 1: 中間インデックス

タスク

整数の配列 @ints が与えられます。

左端の中間インデックス (MI)、つまり可能なすべてのインデックスの中で最小のものを見つけるスクリプトを作成します。

中間インデックスは、ints[0] ints[1] … ints[MI-1] == ints[MI 1] ints[MI 2] … ints[ints.length-1] のインデックスです。

  • MI == 0 の場合、左側の合計は 0 とみなされます。同様に、
  • MI == ints.length - 1 の場合、右辺の合計は 0 とみなされます。

私の解決策

これは比較的簡単です。 0 から入力の長さより 1 小さい位置までループします。各位置で条件が満たされているかどうかを確認します。

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

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

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

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

タスク 2: ポーカー ハンド ランキング

タスク

ドロー ポーカー ハンドは、52 枚のパックから引き出された 5 枚のカードで構成されます。ジョーカーやワイルド カードは含まれません。エースは上位または下位にランク付けされます。

次の 3 つのことを決定するスクリプトを作成します。

  1. 5 枚のカード ハンドは何通り配られますか?
  2. 10 のランクそれぞれで、何通りの異なるハンドを処理できますか?ポーカー ハンドの 10 ランクの説明については、こちらを参照してください: https://en.wikipedia.org/wiki/List_of_poker_hands#Hand-ranking_categories
  3. ステップ 2 で得た 10 個の数値を足し合わせて、ステップ 1 で得た数値と等しいことを確認してください。

私の解決策

長い投稿になるので、最後までお付き合いください。また、入力を必要としないタスクも久しぶりです。私がクリアしたチャレンジの中で、最後のチャレンジは #177 でした。

最初の質問に答えると、配られるカードの組み合わせは 311,875,200 通りあります (52 × 51 × 50 × 49 × 48)。ただし、カードの順序は関係ありません。引いた5枚のカードは、5×4×3×2×1の120通りの配置が可能です。したがって、2,598,960 通りの一意の組み合わせが存在します。

まず、トランプのデッキを作成します。このために、1 から 13 までのランク (カード番号) を持っています。1 はエース、2 から 10 は数字、11 はジャック、12 はクイーン、キングは 13 です。また、スーツ s、c、d もあります。および h (それぞれスペア、クラブ、ダイヤモンド、ハート)。ダブル for ループを使用して、52 枚すべてのカード (ランクとスートのタプル) を生成し、これをデッキと呼ばれるリストに保存します。

次に、デッキの 5 枚のカードの組み合わせをそれぞれループして、どのハンドを持っているかを決定します。最後に結果を印刷します。

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

それは簡単です:)

get_hands 関数では、ランク (カード上の数字) とスート (カード上のシンボル) でソートされたリストの辞書を作成することから始めます。ハンドを決定するためによく使用されるため、ランクの頻度もカウントします。

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

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

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

したがって、カード 10s、10h、9d、8h、2d の場合、次のように設定されます:

  • 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} (1 回表示される 3 つのランクと 2 枚のカードを持つ 1 つのランクがあります)

次に、私がどの手を握っているかを判断します。まずはストレートフラッシュとフラッシュから始めます。これらはカードのスーツを考慮する唯一のハンドであり、ファイブのカードはすべて同じスーツです。これは、cards_by_suit dict に値が 1 つだけある場合に決定されます。

ストレート フラッシュかどうかを判断するために、カードを番号順 (1 ~ 13) に並べます。最初のカードが 1 (エース) で、最後のカードが 13 (キング) の場合、最初のカードを削除し、リストの最後に 14 を追加します。これにより、10、ジャック、クイーン、キング、エースがストレート フラッシュとみなされるようになります。最初のカードの番号と最後のカードの番号の差が 4 の場合、ストレート フラッシュが発生します。

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)

フォー カード ハンド (1 つのランクの 4 枚とランダムな最後のカード) とフルハウス (1 つのランクの 3 枚、異なるランクの 2 枚) の場合、count_by_rank dict を使用してハンドが一致するかどうかを確認できます。指定された基準。

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)

ハンドがストレートかどうかを判断するために、ストレート フラッシュと同様のロジックを使用します。まず、固有のランク (カード番号) が 5 つあることを確認し、それらを順序付け、必要に応じてエースを移動し、高位と低位の差が 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'

スリー カード (同じランクのカード 3 枚、異なるランクのカード 2 枚)、2 ペア (同じランクのカード 2 枚、異なるランクのカード 2 枚、ランダムな最後のカード)、1 ペア (1 つのランクのカード 2 枚)ランク、それぞれ異なるランクの 3 枚のカード) はすべて count_by_rank dict を使用して計算できます。

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

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

最後に、何も一致しない場合は、「ハイ カード」を返します。このハンドを持っているなら、間違いなく自分のハウスを賭けたくないでしょう :)

    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'

display_results 関数は、結果を (ランク順に) 統一されたレイアウトで表示するだけです。冒頭で述べたように、各組み合わせには 120 の順列があり、カードを注文できます。

    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'

出力

    return 'High card'

これを自宅の PC で実行するのに約 15 秒かかりました。

下の行からわかるように、2,598,960 の組み合わせと 311,875,200 の順列があります。これは、出力に表示されると予想されるものと一致します。

以上がインデックスとポーカー ゲームの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。