生成所有5張牌撲克牌手。

[英]Generating all 5 card poker hands


This problem sounds simple at first glance, but turns out to be a lot more complicated than it seems. It's got me stumped for the moment.

乍一看,這個問題聽起來很簡單,但結果卻比看上去要復雜得多。這讓我暫時難住了。

There are 52c5 = 2,598,960 ways to choose 5 cards from a 52 card deck. However, since suits are interchangeable in poker, many of these are equivalent - the hand 2H 2C 3H 3S 4D is equivalent to 2D 2S 3D 3C 4H - simply swap the suits around. According to wikipedia, there are 134,459 distinct 5 card hands once you account for possible suit recolorings.

52c5 = 2,598,960種方法從52張牌牌中選擇5張牌。不過,由於撲克中的套裝是可互換的,所以其中的許多都是等價的——手2H 2C 3H 3S 4D相當於2D 2S 3D 3C 4H——簡單地交換一下套裝。根據維基百科,有134,459個不同的5張牌的手,一旦你解釋了可能的衣服重新着色。

The question is, how do we efficiently generate all these possible hands? I don't want to generate all hands, then eliminate duplicates, as I want to apply the problem to larger numbers of cards, and the number of hands to evaluate fast spirals out of control. My current attempts have centered around either generating depth-first, and keeping track of the currently generated cards to determine what suits and ranks are valid for the next card, or breadth-first, generating all possible next cards, then removing duplicates by converting each hand to a 'canonical' version by recoloring. Here's my attempt at a breadth-first solution, in Python:

問題是,我們如何有效地產生所有這些可能的手?我不想生成所有的手,然后消除重復,因為我想把這個問題應用到更多的卡片上,並且用手的數量來評估快速旋轉失去控制。我目前的嘗試都集中在生成深度優先級,並跟蹤當前生成的卡片,以確定下一張卡片或寬度優先級的適合和級別是有效的,然后生成所有可能的下一種卡片,然后通過重新着色將每只手轉換為“規范”版本,從而刪除重復。這是我的嘗試,在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

Unfortunately, this generates too many hands:

不幸的是,這產生了太多的手:

>>> len(expand_hands(set([()]), 5))
160537

Can anyone suggest a better way to generate just the distinct hands, or point out where I've gone wrong in my attempt?

有沒有人能提出一種更好的方法來產生不同的手,或者指出我的嘗試中哪里出了問題?

12 个解决方案

#1


18  

Your overall approach is sound. I'm pretty sure the problem lies with your make_canonical function. You can try printing out the hands with num_cards set to 3 or 4 and look for equivalencies that you've missed.

你的整體方法是正確的。我很確定問題在於你的make_canonical函數。您可以嘗試將num_cards設置為3或4,並查找您已經錯過的對等項。

I found one, but there may be more:

我找到了一個,但可能還有更多:

# The inputs are equivalent and should return the same value
print make_canonical([8, 12 | 1]) # returns [8, 13]
print make_canonical([12, 8 | 1]) # returns [12, 9]

For reference, below is my solution (developed prior to looking at your solution). I used a depth-first search instead of a breadth-first search. Also, instead of writing a function to transform a hand to canonical form, I wrote a function to check if a hand is canonical. If it's not canonical, I skip it. I defined rank = card % 13 and suit = card / 13. None of those differences are important.

作為參考,下面是我的解決方案(在查看解決方案之前開發)。我使用了深度優先搜索而不是寬度優先搜索。另外,我編寫了一個函數來檢查手是否規范,而不是編寫一個函數來將手轉換成規范形式。如果不是canonical,我就跳過它。我定義了rank = card % 13, suit = card / 13。這些差異都不重要。

import collections

def canonical(cards):
    """
    Rules for a canonical hand:
    1. The cards are in sorted order

    2. The i-th suit must have at least many cards as all later suits.  If a
       suit isn't present, it counts as having 0 cards.

    3. If two suits have the same number of cards, the ranks in the first suit
       must be lower or equal lexicographically (e.g., [1, 3] <= [2, 4]).

    4. Must be a valid hand (no duplicate cards)
    """

    if sorted(cards) != cards:
        return False
    by_suits = collections.defaultdict(list)
    for suit in range(0, 52, 13):
        by_suits[suit] = [card%13 for card in cards if suit <= card < suit+13]
        if len(set(by_suits[suit])) != len(by_suits[suit]):
            return False
    for suit in range(13, 52, 13):
        suit1 = by_suits[suit-13]
        suit2 = by_suits[suit]
        if not suit2: continue
        if len(suit1) < len(suit2):
            return False
        if len(suit1) == len(suit2) and suit1 > suit2:
            return False
    return True

def deal_cards(permutations, n, cards):
    if len(cards) == n:
        permutations.append(list(cards))
        return
    start = 0
    if cards:
        start = max(cards) + 1
    for card in range(start, 52):
        cards.append(card)
        if canonical(cards):
            deal_cards(permutations, n, cards)
        del cards[-1]

def generate_permutations(n):
    permutations = []
    deal_cards(permutations, n, [])
    return permutations

for cards in generate_permutations(5):
    print cards

It generates the correct number of permutations:

它產生正確的排列數:

Cashew:~/$ python2.6 /tmp/cards.py | wc
134459

#2


3  

Here's a Python solution that makes use of numpy and generates the canonical deals as well as their multiplicity. I use Python's itertools module to create all 24 possible permutations of 4 suits and then to iterate over all 2,598,960 possible 5-card deals. Each deal is permuted and converted to a canonical id in just 5 lines. It's quite fast as the loop only goes through 10 iterations to cover all deals and is only needed to manage the memory requirements. All the heavy lifting is done efficiently in numpy except for the use of itertools.combinations. It's a shame this is not supportedly directly in numpy.

這里有一個Python解決方案,它使用numpy並生成規范的協議以及它們的多樣性。我使用Python的itertools模塊創建了所有24種可能的4套組合,然后迭代所有25598960個可能的5張牌。每一項交易都是經過調整的,並在5行中轉換成一個規范的id。它非常快,因為循環只經過10次迭代來覆蓋所有的交易,並且只需要管理內存需求。除了使用itertools.組合之外,所有繁重的工作都在numpy中高效地完成。遺憾的是,這並不是直接在numpy中進行的。

import numpy as np
import itertools

# all 24 permutations of 4 items
s4 = np.fromiter(itertools.permutations(range(4)), dtype='i,i,i,i').view('i').reshape(-1,4)

c_52_5 = 2598960 # = binomial(52,5) : the number of 5-card deals in ascending card-value order
block_n = c_52_5/10
def all5CardDeals():
    '''iterate over all possible 5-card deals in 10 blocks of 259896 deals each'''
    combos = itertools.combinations(range(52),5)
    for i in range(0, c_52_5, block_n):
        yield np.fromiter(combos, dtype='i,i,i,i,i', count=block_n).view('i').reshape(-1,5)

canon_id = np.empty(c_52_5, dtype='i')
# process all possible deals block-wise.
for i, block in enumerate(all5CardDeals()):
    rank, suit = block/4, block%4     # extract the rank and suit of each card
    d = rank[None,...]*4 + s4[:,suit] # generate all 24 permutations of the suits
    d.sort(2)                         # re-sort into ascending card-value order
    # convert each deal into a unique integer id
    deal_id = d[...,0]+52*(d[...,1]+52*(d[...,2]+52*(d[...,3]+52*d[...,4])))
    # arbitrarily select the smallest such id as the canonical one 
    canon_id[i*block_n:(i+1)*block_n] = deal_id.min(0)
# find the unique canonical deal ids and the index into this list for each enumerated hand
unique_id, indices = np.unique(canon_id, return_inverse=True)
print len(unique_id) # = 134459
multiplicity = np.bincount(indices)
print multiplicity.sum() # = 2598960 = c_52_5

#3


2  

Your problem sounded interesting, so i simple tried to implements it by just looping over all possible hands in a sorted way. I've not looked at your code in details, but it seems my implementation is quite different from yours. Guess what count of hands my script found: 160537

您的問題聽起來很有趣,所以我簡單地嘗試着用排序的方法來實現它。我沒有詳細地看你的代碼,但是看起來我的實現和你的很不一樣。猜猜看,我的腳本發現了什么?

  • My hands are always sorted, e.g. 2 3 4 4 D
  • 我的手總是排好序,例如:2 3 4 4 D。
  • If there are 2 equal cards, the color is also sorted (colors are just called 0,1,2,3)
  • 如果有兩張相等的卡片,顏色也會被分類(顏色是0,1,2,3)
  • the first card has always color 0, the second color 0 or 1
  • 第一張牌的顏色總是0,第二個顏色是0或1。
  • A card can only have the color of an previous card or the next bigger number, e.g. if card 1+2 have color 0, card three can only have the colors 0 or 1
  • 一張卡片只能有前一張牌的顏色或下一個較大的數字,例如,如果卡片1+2有顏色0,卡片3只能有顏色0或1。

Are you sure, the number on wikipedia is correct?

你確定,維基百科上的數字是正確的嗎?

count = 0
for a1 in range(13):
    c1 = 0
    for a2 in range(a1, 13):
        for c2 in range(2):
            if a1==a2 and c1==c2:
                continue
            nc3 = 2 if c1==c2 else 3
            for a3 in range(a2, 13):
                for c3 in range(nc3):
                    if (a1==a3 and c1>=c3) or (a2==a3 and c2>=c3):
                        continue
                    nc4 = nc3+1 if c3==nc3-1 else nc3
                    for a4 in range(a3, 13):
                        for c4 in range(nc4):
                            if (a1==a4 and c1>=c4) or (a2==a4 and c2>=c4) or (a3==a4 and c3>=c4):
                                continue
                            nc5 = nc4+1 if (c4==nc4-1 and nc4!=4) else nc4
                            for a5 in range(a4, 13):
                                for c5 in range(nc5):
                                    if (a1==a5 and c1>=c5) or (a2>=a5 and c2>=c5) or (a3==a5 and c3>=c5) or (a4==a5 and c4>=c5):
                                        continue
                                    #print([(a1,c1),(a2,c2),(a3,c3),(a4,c4),(a5,c5)])
                                    count += 1
print("result: ",count)

#4


1  

I'm not a poker player, so the details of hand precedence are beyond me. But it seems like the problem is that you are traversing the space of "sets of 5 cards" by generating sets from the deck, when you should be traversing the space of "distinct poker hands".

我不是撲克玩家,所以手的優先權比我更重要。但問題似乎在於,當你要穿越“獨特的撲克手”的空間時,你正在從甲板上生成“5張牌”的空間。

The space of distinct hands will require a new grammar. The important thing is to capture exactly the information that is relevant to hand precedence. For example, there are only 4 hands that are royal flushes, so those hands can be described as the symbol "RF" plus a suit designator, like "RFC" for royal flush in clubs. A 10-high heart flush could be "FLH10" (not sure if there are other precedence characteristics of flushes, but I think that's all you need to know). A hand that is "2C 2S AH 10C 5D" would be a longer expression, something like "PR2 A 10 5" if I undestand your initial problem statement.

不同的手的空間需要一個新的語法。重要的是准確地捕獲與手動優先級相關的信息。舉個例子,只有4只手是皇家的沖鋒,所以這些手可以被描述為“RF”的符號,再加上一套衣服的名稱,就像“RFC”(RFC)一樣,可以在俱樂部里使用。10個高的心臟沖水可能是“FLH10”(不確定是否有其他優先級特征,但我認為這就是你所需要知道的)。一個“2C 2S AH 10C 5D”的手將會是一個更長的表達,比如“PR2 A 10 5”,如果我堅持你的初始問題的話。

Once you have defined the grammar of distinct hands, you can express it as regular expressions and that will tell you how to generate the entire space of distinct hands. Sounds like fun!

一旦你定義了不同的手的語法,你可以將它表達為正則表達式,它會告訴你如何生成完全不同的手的空間。聽起來很有趣!

#5


1  

You could simply give all hands a canonical ordering of values (A to K), then assign abstract suit letters according to their order of first appearance in that order.

你可以簡單地給所有的人一個標准的值(a到K)的順序,然后根據他們第一次出現的順序來分配抽象的適合的字母。

Example: JH 4C QD 9C 3D would convert to 3a 4b 9b Jc Qa.

示例:JH 4C QD 9C 3D將轉換為3a 4b9b Jc Qa。

Generation should work best as dynamic programming:

在動態規划中,生成應該是最好的:

  • start with a set of a single hand that is empty,
  • 從一個空的單手開始,
  • make a new set:
    • for each hand in the old set, generate each possible hand by adding one of the remaining cards
    • 對於舊集合中的每只手,通過添加剩下的一張牌來生成每個可能的手。
    • canonicalize all new hands
    • 規范化所有新的手
    • remove duplicates
    • 刪除重復的
  • 制作一個新的集合:在舊的集合中,每只手都可以通過添加一個將所有新手刪除重復的牌的剩余的卡片來生成每一個可能的手。

#6


1  

Initial input:

初始輸入:

H 0 0 0 0 0 0 0 0 0 0 0 0 0
C 1 0 0 0 0 0 0 0 0 0 0 0 0
D 1 0 0 0 0 0 0 0 0 0 0 0 0
S 1 1 0 0 0 0 0 0 0 0 0 0 0
+ A 2 3 4 5 6 7 8 9 T J Q K

Step 1: for each rank greater than or equal the highest rank used, set all suits in that rank to 0. you can get away with only checking higher cards because lower combinations will be checked by the lower starting points.

第一步:對於每個級別大於或等於最高等級的人,將所有的套裝設置為0。你可以只檢查更高的牌,因為較低的組合會被較低的起點檢查。

H 0 0 0 0 0 0 0 0 0 0 0 0 0
C 1 0 0 0 0 0 0 0 0 0 0 0 0
D 1 0 0 0 0 0 0 0 0 0 0 0 0
S 1 0 0 0 0 0 0 0 0 0 0 0 0
+ A 2 3 4 5 6 7 8 9 T J Q K

Step 2: Collapse to distinct rows

步驟2:崩潰到不同的行。

0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0
A 2 3 4 5 6 7 8 9 T J Q K

Step 3: Climb back up determining first suit that match each distinct row, and choose the suits which match the distinct rows (identified by a *)

第3步:爬回確定匹配每一行的第一套衣服,並選擇匹配不同行的套裝(由*標識)

H 0 * 0 0 0 0 0 0 0 0 0 0 0
C 1 0 0 0 0 0 0 0 0 0 0 0 0
D 1 * 0 0 0 0 0 0 0 0 0 0 0
S 1 1 0 0 0 0 0 0 0 0 0 0 0
+ A 2 3 4 5 6 7 8 9 T J Q K

Now showing the repeat for rank 3

現在顯示3級的重復。

H 0 0 0 0 0 0 0 0 0 0 0 0 0
C 1 0 0 0 0 0 0 0 0 0 0 0 0
D 1 0 0 0 0 0 0 0 0 0 0 0 0
S 1 1 0 0 0 0 0 0 0 0 0 0 0
+ A 2 3 4 5 6 7 8 9 T J Q K

0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0
A 2 3 4 5 6 7 8 9 T J Q K

H 0 0 * 0 0 0 0 0 0 0 0 0 0
C 1 0 0 0 0 0 0 0 0 0 0 0 0
D 1 0 * 0 0 0 0 0 0 0 0 0 0
S 1 1 * 0 0 0 0 0 0 0 0 0 0
+ A 2 3 4 5 6 7 8 9 T J Q K

Step 4: Once there are 5 cells set to 1, increment the total possible suit abstracted hands count by 1 and recurse up.

步驟4:一旦有5個單元格設置為1,就可以將所有可能的suit抽象為1並遞歸。

The total number of suit abstracted hands possible is 134,459. This is the code I wrote to test it out:

可抽調的衣服總數是134,459。這是我寫的測試代碼:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication20
{
    struct Card
    {
        public int Suit { get; set; }
        public int Rank { get; set; }
    }
    
    class Program
    {
        static int ranks = 13;
        static int suits = 4;
        static int cardsInHand = 5;

        static void Main(string[] args)
        {
            List<Card> cards = new List<Card>();
            //cards.Add(new Card() { Rank = 0, Suit = 0 });
            int numHands = GenerateAllHands(cards);
    
            Console.WriteLine(numHands);
            Console.ReadLine();
        }
  
        static int GenerateAllHands(List<Card> cards)
        {
            if (cards.Count == cardsInHand) return 1;
    
            List<Card> possibleNextCards = GetPossibleNextCards(cards);
    
            int numSubHands = 0;
    
            foreach (Card card in possibleNextCards)
            {
                List<Card> possibleNextHand = cards.ToList(); // copy list
                possibleNextHand.Add(card);
                numSubHands += GenerateAllHands(possibleNextHand);
            }
    
            return numSubHands;
        }
    
        static List<Card> GetPossibleNextCards(List<Card> hand)
        {
            int maxRank = hand.Max(x => x.Rank);
            
            List<Card> result = new List<Card>();
    
            // only use ranks >= max
            for (int rank = maxRank; rank < ranks; rank++)
            {
                List<int> suits = GetPossibleSuitsForRank(hand, rank);
                var possibleNextCards = suits.Select(x => new Card { Rank = rank, Suit = x });
                result.AddRange(possibleNextCards);
            }
    
            return result;
        }
    
        static List<int> GetPossibleSuitsForRank(List<Card> hand, int rank)
        {
            int maxSuit = hand.Max(x => x.Suit);
    
            // select number of ranks of different suits
            int[][] card = GetArray(hand, rank);
    
            for (int i = 0; i < suits; i++)
            {
                card[i][rank] = 0;
            }
    
            int[][] handRep = GetArray(hand, rank);
    
            // get distinct rank sets, then find which ranks they correspond to
            IEnumerable<int[]> distincts = card.Distinct(new IntArrayComparer());
    
            List<int> possibleSuits = new List<int>();
    
            foreach (int[] row in distincts)
            {
                for (int i = 0; i < suits; i++)
                {
                    if (IntArrayComparer.Compare(row, handRep[i]))
                    {
                        possibleSuits.Add(i);
                        break;
                    }
                }
            }
    
            return possibleSuits;
        }
    
        class IntArrayComparer : IEqualityComparer<int[]>
        {
            #region IEqualityComparer<int[]> Members
    
            public static bool Compare(int[] x, int[] y)
            {
                for (int i = 0; i < x.Length; i++)
                {
                    if (x[i] != y[i]) return false;
                }
    
                return true;
            }
    
            public bool Equals(int[] x, int[] y)
            {
                return Compare(x, y);
            }
    
            public int GetHashCode(int[] obj)
            {
                return 0;
            }

            #endregion
        }

        static int[][] GetArray(List<Card> hand, int rank)
        {
            int[][] cards = new int[suits][];
            for (int i = 0; i < suits; i++)
            {
                cards[i] = new int[ranks];
            }

            foreach (Card card in hand)
            {
                cards[card.Suit][card.Rank] = 1;
            }
    
            return cards;
        }
    }
}

Hopefully it is broken up enough to be easily understandable.

希望它被分解的足夠容易理解。

#7


1  

Here is a simple and straightforward algorithm for reducing hands to a canonical one based on suit permutatoins.

這是一個簡單和直接的算法,以減少手到一個標准的基於適合的permutatoins。

  1. convert hand to four bitsets, one per suit representing cards of the suit
  2. 將手轉換為4個位組,每一套代表套裝的牌。
  3. sort the bitsets
  4. 對bitsets排序
  5. convert bitsets back into hand
  6. 將bitset轉換回手動。

This is what the algorithm looks like in C++, with some implied Suit and CardSet classes. Note that the return statement converts the hand by concatenating the bitstrings.

這就是算法在c++中的樣子,有一些默認的Suit和CardSet類。注意,return語句通過連接位串來轉換手。

CardSet CardSet::canonize () const
{
  int smasks[Suit::NUM_SUIT];
  int i=0;
  for (Suit s=Suit::begin(); s<Suit::end(); ++s)
    smasks[i++] = this->suitMask (s);

  sort (smasks, smasks+Suit::NUM_SUIT);

  return CardSet(
    static_cast<uint64_t>(smasks[3])                        |
    static_cast<uint64_t>(smasks[2]) << Rank::NUM_RANK      |
    static_cast<uint64_t>(smasks[1]) << Rank::NUM_RANK*2    |
    static_cast<uint64_t>(smasks[0]) << Rank::NUM_RANK*3);
}

#8


0  

Look at Pokersource. The problem gets even worse when you're considering completing hands given some cards already drawn.

看看Pokersource。當你考慮完成一些已經畫好的牌時,問題就更嚴重了。

The guy behind PokerStove did a great job in this direction, but the source is disclosed.

poker爐子后面的人在這個方向上做得很好,但是消息來源被披露了。

#9


0  

Generating equivalence classes for 5 card hands is not an easy task. When I need this I usually use the http://www.vpgenius.com/ webpage. At http://www.vpgenius.com/video-poker/games/ you can choose which variety of poker game you need, and in the "Programming tab" you have an section on "Unique Suit Patterns". So just copying that and loading into program might be easier than trying to generate your own.

為5個卡片手生成等價類不是一件容易的事情。當我需要時,我通常使用http://www.vpgenius.com/網頁。在http://www.vpgenius.com/videopoker/games/你可以選擇你需要的撲克游戲種類,在“編程標簽”中你有一節“獨特的西裝模式”。因此,復制並加載到程序中可能比創建自己的程序更容易。

#10


0  

Take a look here:

看一看:

http://specialk-coding.blogspot.com/

http://specialk-coding.blogspot.com/

http://code.google.com/p/specialkpokereval/

http://code.google.com/p/specialkpokereval/

These regard a 5-card hand (and a 7-card hand) as an integer, the sum the individual cards, which is independent of the suit. Exactly what you need.

這些都是一個5張牌的手(和7張牌的手)作為一個整數,和單獨的卡片,獨立於訴訟。正是你需要的。

This is part of a scheme for quickly ranking 7- and 5-card hands, written in Objective-C and Java.

這是在Objective-C和Java中快速排序7- 5卡手的計划的一部分。

#11


0  

If you are just interested in hands that result in different hand rankings, there are actually only 7462 distinct hand classes that have to be considered (see Wikipedia).

如果你只是感興趣的手,結果在不同的手排名,實際上只有7462個不同的手類必須被考慮(參見維基百科)。

By creating a table with an example for each class and their accompanying multiplicity you can check all relevant hands weighted with their probability quite fast. That is, assuming that no cards are known and therefore fixed beforehand already.

通過為每一個類創建一個表及其伴隨的多樣性,您可以快速地檢查所有相關的手。也就是說,假設沒有已知的卡片,因此事先已經確定了。

#12


0  

Chances are you really want to generate the number of distinct hands, in the sense of non-equivalent. In that case, according to the wikipedia article there are 7462 possible hands. Here is a python snippet that will enumerate them all.

很可能你真的想要產生不同的手的數量,在非等價的意義上。在這種情況下,根據維基百科的文章,有7462個可能的手。下面是將枚舉它們的python代碼片段。

The logic is simple: there is one hand for each 5-set of ranks; in addition, if all the ranks are distinct, another, different kind of hand can be formed by making all the suits match.

邏輯很簡單:每一組5組的隊伍都有一只手;此外,如果所有的等級都是不同的,另一種不同的手可以通過使所有的衣服匹配而形成。

count = 0 

for i in range(0,13):
    for j in range (i,13):
        for k in range(j,13):
            for l in range(k,13):
                for m in range(l,13):
                    d = len(set([i,j,k,l,m])) # number of distinct ranks
                    if d == 1: continue    # reject nonsensical 5-of-a-kind
                    count += 1
                    # if all the ranks are distinct then 
                    # count another hand with all suits equal
                    if d == 5: count += 1

print count   # 7462

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2010/09/30/af9390f4affde5c43e216ab5ce35e0ac.html



 
  © 2014-2022 ITdaan.com 联系我们: