指數和撲克遊戲

Barbara Streisand
發布: 2024-10-20 20:18:30
原創
951 人瀏覽過

Index and poker games

每週挑戰 291

穆罕默德·S·安瓦爾 (Mohammad S. Anwar) 每週都會發出“每週挑戰”,讓我們所有人都有機會為兩週的任務提出解決方案。我的解決方案先用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:撲克牌手牌排名

任務

一手抽牌撲克由 5 張牌組成,從 52 張牌中抽取:沒有小丑,沒有百搭牌。 A 的排名可以高也可以低。

寫一個腳本來決定以下三件事:

  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)。然而,卡片的順序並不重要。對於任五張抽牌,它們可以以 120 種方式排列(5 × 4 × 3 × 2 × 1)。因此共有 2,598,960 種獨特的組合。

我先創建一副紙牌。為此,我的等級(牌號)為 1 到 13。1 是 A,2 到 10 是數字,11 是 Jack,12 是 Queen,K 是 13。我還有一套花色 s、c、d和 h(分別為備用、梅花、菱形和紅心)。使用雙 for 循環,我產生所有 52 張牌(等級和花色的元組)並將其儲存在名為牌組的清單中。

然後,我循環遍歷牌組中每個獨特的五張牌組合,並確定我持有哪隻手牌。最後我列印結果。

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}(三個等級出現一次,一張有兩張牌)

然後是時候確定我握著哪隻手了。我們將從同花順和同花開始。這些是唯一考慮紙牌花色的手牌,並且所有五張牌都是相同花色的。這是當 cards_by_suit 字典只有一個值時確定的。

為了確定它是否是同花順,我按數字對牌進行排序(從 1 到 13)。如果第一張牌是 1(A)而最後一張牌是 13(K),我會刪除第一張牌並將 14 加到清單的末尾。這使得 10、J、Q、K 和 A 被視為同花順。當第一張牌的數字與最後一張牌的數字之差為四時,即為同花順。

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)
登入後複製

對於四張同花牌(四張一牌,隨機最後一張牌)和葫蘆(三張一牌,兩張不同牌),我可以使用 count_by_rank 字典來查看這手牌是否匹配指定的標準。

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)
登入後複製

為了確定這手牌是否為直牌,我使用與同花順類似的邏輯。我首先檢查我是否有五個唯一的等級(卡號),對它們進行排序,如果需要則移動 A,並檢查高低之間的差異是否為 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'
登入後複製

三張同種(三張同點數的牌,兩張不同點數的牌),兩對(兩張同點數的牌,兩張不同點數的牌,隨機最後一張牌),一對(兩張同點數的牌)等級(每張不同等級的三張牌)都可以使用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'
登入後複製

最後,如果沒有符合項,則回傳「高牌」。如果你拿著這手牌,你絕對不會想拿你的房子去賭:)

    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'
登入後複製

在我的家用電腦上運行大約需要 15 秒。

從底行可以看到,我們有 2,598,960 種組合和 311,875,200 種排列。這與我們期望在輸出中看到的內容相符。

以上是指數和撲克遊戲的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!