Generating all 5 card poker hands

前端 未结 11 641
再見小時候
再見小時候 2020-12-23 09:53

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

11条回答
  •  一生所求
    2020-12-23 10:15

    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.

    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
    

提交回复
热议问题