Indeks dan permainan poker

Barbara Streisand
Lepaskan: 2024-10-20 20:18:30
asal
951 orang telah melayarinya

Index and poker games

Cabaran Mingguan 291

Setiap minggu Mohammad S. Anwar menghantar Cabaran Mingguan, peluang untuk kita semua mencari penyelesaian kepada dua tugas mingguan. Penyelesaian saya ditulis dalam Python terlebih dahulu, dan kemudian ditukar kepada Perl. Ini cara yang bagus untuk kita semua mempraktikkan beberapa pengekodan.

Cabaran, Penyelesaian saya

Tugasan 1: Indeks Tengah

Tugasan

Anda diberi tatasusunan integer, @ints.

Tulis skrip untuk mencari indeks tengah paling kiri (MI) iaitu yang terkecil di antara semua yang mungkin.

Indeks tengah ialah indeks dengan ints[0] ints[1] … ints[MI-1] == ints[MI 1] ints[MI 2] … ints[ints.length-1].

  • Jika MI == 0, jumlah sebelah kiri dianggap sebagai 0. Begitu juga,
  • jika MI == ints.panjang - 1, jumlah sebelah kanan dianggap sebagai 0.

penyelesaian saya

Ini agak lurus ke hadapan. Saya gelung melalui kedudukan dari 0 hingga satu kurang daripada panjang input. Pada setiap kedudukan saya melihat jika syarat dipenuhi.

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
Salin selepas log masuk
Salin selepas log masuk

Contoh

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

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

$ ./ch-1.py 2 5
-1
Salin selepas log masuk
Salin selepas log masuk

Tugasan 2: Kedudukan Tangan Poker

Tugasan

Sebuah tangan poker cabutan terdiri daripada 5 kad, diambil daripada pek 52: tiada pelawak, tiada kad liar. Ace boleh berpangkat sama ada tinggi atau rendah.

Tulis skrip untuk menentukan tiga perkara berikut:

  1. Berapa bilangan tangan 5 kad yang berbeza boleh diuruskan?
  2. Berapa banyak tangan yang berbeza bagi setiap 10 pangkat boleh ditangani? Lihat di sini untuk penerangan tentang 10 peringkat tangan Poker: https://en.wikipedia.org/wiki/List_of_poker_hands#Hand-ranking_categories
  3. Semak sepuluh nombor yang anda dapat dalam langkah 2 dengan menambahkannya bersama-sama dan menunjukkan bahawa ia adalah sama dengan nombor yang anda dapat dalam langkah 1.

penyelesaian saya

Ikat, kerana ini akan menjadi jawatan yang panjang. Ia juga merupakan kali pertama dalam masa yang lama bahawa tugasan tidak memerlukan sebarang input. Dalam cabaran yang telah saya selesaikan, yang terakhir ialah #177.

Untuk menjawab soalan pertama, terdapat 311,875,200 kemungkinan pilih atur kad yang boleh diuruskan (52 × 51 × 50 × 49 × 48). Walau bagaimanapun, susunan kad tidak penting. Untuk mana-mana lima kad yang dilukis, ia boleh disusun dalam 120 cara (5 × 4 × 3 × 2 × 1). Oleh itu terdapat 2,598,960 kombinasi unik.

Saya mulakan dengan mencipta dek kad. Untuk ini saya mempunyai pangkat (nombor kad) 1 hingga 13. 1 ialah ace, 2 hingga 10 ialah nombor, 11 ialah Jack, 12 ialah Ratu dan Raja ialah 13. Saya juga mempunyai saman s, c, d dan h (masing-masing alat ganti, kelab, berlian dan jantung). Dengan menggunakan gelung berganda, saya menjana kesemua 52 kad (satu tuple pangkat dan sut) dan menyimpannya dalam senarai yang dipanggil dek.

Saya kemudian mengulangi setiap gabungan lima kad dek yang unik dan menentukan tangan yang saya pegang. Akhirnya saya mencetak hasilnya.

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
Salin selepas log masuk
Salin selepas log masuk

Itu bahagian yang mudah :)

Untuk fungsi get_hands, saya mulakan dengan membuat dict senarai yang disusun mengikut pangkat (nombor pada kad) dan sut (simbol pada kad). Saya juga mengira kekerapan pangkat, kerana ini sering digunakan untuk menentukan tangan.

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

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

$ ./ch-1.py 2 5
-1
Salin selepas log masuk
Salin selepas log masuk

Jadi untuk kad 10s, 10j, 9d, 8j, 2d, perkara berikut akan ditetapkan:

  • kad_mengikut_pangkat {10: ['s', 'h'], 9: ['d'], 8: ['h'], 2: ['d']}
  • cards_by_suit {'s': [10], 'h': [10, 8], 'd': [9, 2]}
  • kira_demi_pangkat {1: 3, 2: 1} (terdapat tiga pangkat yang muncul sekali, dan satu yang mempunyai dua kad)

Masanya untuk menentukan tangan yang saya pegang. Kita akan mulakan dengan siram lurus dan siram. Ini adalah satu-satunya tangan yang mempertimbangkan sut kad, dan semua kad fives adalah sut yang sama. Ini ditentukan apabila dict card_by_suit hanya mempunyai satu nilai.

Untuk menentukan sama ada ia adalah siram lurus, saya memesan kad secara berangka (dari 1 hingga 13). Jika kad pertama ialah 1 (sebuah ace) dan kad terakhir ialah 13 (raja), saya mengeluarkan kad pertama dan menambah 14 pada penghujung senarai. Ini membolehkan 10, Jack, Queen, King dan Ace dianggap sebagai straight flush. Siram lurus berlaku apabila perbezaan antara nombor kad pertama dan kad terakhir ialah empat.

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)
Salin selepas log masuk

Untuk tangan empat jenis (empat daripada satu pangkat, dan kad terakhir rawak) dan rumah penuh (tiga daripada satu pangkat, dua daripada pangkat yang berbeza), saya boleh menggunakan dict count_by_rank untuk melihat sama ada tangan itu sepadan kriteria yang ditetapkan.

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)
Salin selepas log masuk

Untuk menentukan sama ada tangan lurus, saya menggunakan logik yang sama dengan straight flush. Saya mula-mula menyemak sama ada saya mempunyai lima kedudukan unik (nombor kad), memesannya, gerakkan ace jika perlu dan semak sama ada perbezaan antara tinggi dan rendah ialah 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'
Salin selepas log masuk

Tiga jenis (tiga kad satu pangkat, dua kad pangkat berbeza), dua pasang (dua kad satu pangkat, dua kad pangkat berbeza, kad terakhir rawak), satu pasangan (dua kad satu pangkat, tiga kad pangkat berbeza setiap satu) semuanya boleh dikira menggunakan 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'
Salin selepas log masuk

Dan akhirnya jika tiada yang sepadan, kembalikan 'Kad tinggi'. Anda pasti tidak mahu bertaruh rumah anda jika anda memegang tangan ini :)

    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'
Salin selepas log masuk

Fungsi display_results hanya memaparkan keputusan (disusun mengikut pangkat) dalam susun atur beruniform. Seperti yang dinyatakan pada permulaan untuk setiap kombinasi terdapat 120 pilih atur kad boleh dipesan.

    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'
Salin selepas log masuk

Keluaran

    return 'High card'
Salin selepas log masuk

Ini mengambil masa kira-kira 15 saat untuk dijalankan pada PC rumah saya.

Seperti yang dapat kita lihat dari baris bawah, kita mempunyai 2,598,960 kombinasi dan 311,875,200 pilih atur. Ini sepadan dengan apa yang kami jangkakan untuk lihat dalam output.

Atas ialah kandungan terperinci Indeks dan permainan poker. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!