# 生成所有5张牌扑克牌

``# 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` `

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

` `# 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]` `

` `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 (eg, [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` `

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

` `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` `

• 我的手总是sorting，例如2 3 4 4 D
• 如果有两张相同的牌，颜色也被分类（颜色只被称为0,1,2,3）
• 第一张牌总是颜色0，第二种颜色是0或1
• 一张卡片只能有以前卡片的颜色或下一个较大的数字，例如，如果卡片1 + 2的颜色为0，则卡片3只能有0或1的颜色

` `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)` `

• 从一组空单手开始，
• 做一个新的集合：
• 对于旧套装中的每只手，通过添加剩余的牌中的一个来产生每个可能的牌
• 规范所有新手
• 删除重复项

` `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 TJQK` `

` `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 TJQK` `

` `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 TJQK` `

` `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 TJQK` `

` `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 TJQK 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 TJQK 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 TJQK` `

` `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;    }  } }` `

1. 将手转换成四个比特集，每个西装一个代表西装的牌
2. sorting位集
3. 将比特集转换回手中

` `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); }` `

PokerStove背后的家伙在这个方面做得很好，但是消息来源被披露了。

` `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` `
Interesting Posts