高效算法,订购“ 5出7”牌扑克(非直/非同花)牌分而治之

时间:2019-02-06 17:39:30

标签: python algorithm performance poker

考虑长度为7的排序列表,其中每个条目x是数字2 <= x <= 14,任何条目的重复计数都不能超过4。这里的假设是,高性能算法已经确定我们的手是非直/非平的。

在线扑克站点将对高性能算法感兴趣,从而关注在此情况下获得5张最佳扑克牌的下一步。

使用Python编写不导入模块的程序是对此类算法进行原型设计的好方法。

“怪物规模”在线扑克网站很可能不需要我们的任何帮助,但是看到为速度而设计的算法将很有趣。在问题中

7 Card Poker Hand Evaluator

从2010年开始对此进行了检查,但是许多链接断开了。了解当今使用最快的已知算法的状态将非常高兴。

  

问题:下面讨论的算法是否已知?是否已确定某些算法在性能方面很出色?

我的工作

我注意到长度为7的列表有一个中点,并且算法可以包含“组合对称性”和结构。我们在以下代码中实现此逻辑。可以想到用汇编程序编写的快速的程序,该程序计算解决方案的GOTO号偏移量。

注意:我也有一个单程排序例程,该例程可以获取任何7张卡片并确定是否可以进行顺子或同花。但是建议我让我的问题更集中,所以这里不讨论。

Python程序:

hand=[2,2,7,7,8,11,12]
hand=[2,3,4,7,7,7,11]


start_spot = 3
end_spot = 3

if hand[3] == hand[4]:
    if hand[4] == hand[5]:
        if hand[5] == hand[6]:
            end_spot = 6
        else:
            end_spot = 5
    else:
        end_spot = 4

if hand[3] == hand[2]:
    if hand[2] == hand[1]:
        if hand[1] == hand[0]:
            start_spot = 0
        else:
            start_spot = 1
    else:
        start_spot = 2

if end_spot - start_spot == 3:
    if end_spot == 6:
        Kick = hand[start_spot-1]
    else:
        Kick = hand[6]
    best5 = [Kick,hand[start_spot],hand[start_spot+1],hand[start_spot+2],hand[start_spot+3]]
    print(hand, best5, 'four of a kind')
    raise SystemExit
else:
    pass


def multCount(c1,c2,c3):
    pc = 0
    if c1 == c2: pc = pc + 1
    if c2 == c3: pc = pc + 10
    return pc

pc_r = multCount(hand[4],hand[5],hand[6])
pc_l = multCount(hand[2],hand[1],hand[0])

if start_spot == 3 and end_spot == 3:
    if   pc_l ==  0 and pc_r == 0:        
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'no pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 1:   
        best5 = [hand[2],hand[3],hand[6],hand[4],hand[5]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 10:       
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 11:       
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'trips')
        raise SystemExit

    elif pc_l == 1  and pc_r == 0:        
        best5 = [hand[4],hand[5],hand[6],hand[1],hand[2]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 1:       
        best5 = [hand[6],hand[1],hand[2],hand[4],hand[5]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 10:       
        best5 = [hand[4],hand[1],hand[2],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 11:       
        best5 = [hand[1],hand[2],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    elif pc_l == 10 and pc_r == 0:        
        best5 = [hand[4],hand[5],hand[6],hand[0],hand[1]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 1:       
        best5 = [hand[6],hand[0],hand[1],hand[4],hand[5]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 10:       
        best5 = [hand[4],hand[0],hand[1],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 11:       
        best5 = [hand[0],hand[1],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    elif pc_l == 11 and pc_r == 0:        
        best5 = [hand[5],hand[6],hand[0],hand[1],hand[2]]
        print(hand, best5, 'trips')
        raise SystemExit
    elif pc_l == 11 and pc_r == 1:       
        best5 = [hand[4],hand[5],hand[0],hand[1],hand[2]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 11 and pc_r == 10:       
        best5 = [hand[5],hand[6],hand[0],hand[1],hand[2]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 11 and pc_r == 11:       
        best5 = [hand[1],hand[2],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    else:
        pass



if start_spot == 3 and end_spot == 4:
    if   pc_l ==  0 and pc_r == 0:        
        best5 = [hand[2],hand[5],hand[6],hand[3],hand[4]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 1:
        print("ERROR 1")
        pass # can't happen
        raise SystemExit    
    elif pc_l ==  0 and pc_r == 10:       
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 11:       
        print("ERROR 2")
        pass # can't happen
        raise SystemExit

    elif pc_l == 1  and pc_r == 0:        
        best5 = [hand[6],hand[1],hand[2],hand[3],hand[4]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 1:       
        print("ERROR 3")
        pass # can't happen
        raise SystemExit    
    elif pc_l == 1  and pc_r == 10:       
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 1  and pc_r == 11:       
        print("ERROR 4")
        pass # can't happen
        raise SystemExit

    elif pc_l == 10 and pc_r == 0:        
        best5 = [hand[6],hand[0],hand[1],hand[3],hand[4]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 1:       
        print("ERROR 5")
        pass # can't happen
        raise SystemExit
    elif pc_l == 10 and pc_r == 10:       
        best5 = [hand[4],hand[0],hand[1],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 11:       
        print("ERROR 6")
        pass # can't happen
        raise SystemExit

    elif pc_l == 11 and pc_r == 0:        
        best5 = [hand[3],hand[4],hand[0],hand[1],hand[2]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 11 and pc_r == 1:       
        print("ERROR 7")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 10:       
        best5 = [hand[5],hand[6],hand[0],hand[1],hand[2]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 11 and pc_r == 11:       
        print("ERROR 8")
        pass # can't happen
        raise SystemExit

    else:
        pass


if start_spot == 2 and end_spot == 3:
    if   pc_l ==  0 and pc_r == 0:        
        best5 = [hand[4],hand[5],hand[6],hand[2],hand[3]]
        print(hand, best5, 'one pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 1:
        best5 = [hand[6],hand[2],hand[3],hand[4],hand[5]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 10:       
        best5 = [hand[4],hand[2],hand[3],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 11:       
        print("ERROR 9")
        pass # can't happen
        raise SystemExit

    elif pc_l == 1  and pc_r == 0:        
        print("ERROR 10")
        pass # can't happen
        raise SystemExit
    elif pc_l == 1  and pc_r == 1:       
        print("ERROR 11")
        pass # can't happen
        raise SystemExit    
    elif pc_l == 1  and pc_r == 10:       
        print("ERROR 12")
        pass # can't happen
        raise SystemExit
    elif pc_l == 1  and pc_r == 11:       
        print("ERROR 13")
        pass # can't happen
        raise SystemExit

    elif pc_l == 10 and pc_r == 0:        
        best5 = [hand[6],hand[0],hand[1],hand[2],hand[3]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 1:       
        best5 = [hand[6],hand[2],hand[3],hand[4],hand[5]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 10:       
        best5 = [hand[4],hand[2],hand[3],hand[5],hand[6]]
        print(hand, best5, 'two pair')
        raise SystemExit
    elif pc_l == 10 and pc_r == 11:       
        print("ERROR 14")
        pass # can't happen
        raise SystemExit

    elif pc_l == 11 and pc_r == 0:        
        print("ERROR 15")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 1:       
        print("ERROR 16")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 10:       
        print("ERROR 17")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 11:       
        print("ERROR 18")
        pass # can't happen
        raise SystemExit

    else:
        pass


if start_spot == 2 and end_spot == 4:
    if   pc_l ==  0 and pc_r == 0:        
        best5 = [hand[5],hand[6],hand[2],hand[3],hand[4]]
        print(hand, best5, 'trips')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 1:
        print("ERROR 19")
        pass # can't happen
        raise SystemExit    
    elif pc_l ==  0 and pc_r == 10:       
        best5 = [hand[5],hand[6],hand[2],hand[3],hand[4]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l ==  0 and pc_r == 11:       
        print("ERROR 20")
        pass # can't happen
        raise SystemExit

    elif pc_l == 1  and pc_r == 0:        
        print("ERROR 21")
        pass # can't happen
        raise SystemExit
    elif pc_l == 1  and pc_r == 1:       
        print("ERROR 22")
        pass # can't happen
        raise SystemExit    
    elif pc_l == 1  and pc_r == 10:       
        print("ERROR 23")
        pass # can't happen
        raise SystemExit
    elif pc_l == 1  and pc_r == 11:       
        print("ERROR 24")
        pass # can't happen
        raise SystemExit

    elif pc_l == 10 and pc_r == 0:        
        best5 = [hand[0],hand[1],hand[2],hand[3],hand[4]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 10 and pc_r == 1:       
        print("ERROR 25")
        pass # can't happen
        raise SystemExit
    elif pc_l == 10 and pc_r == 10:       
        best5 = [hand[5],hand[6],hand[2],hand[3],hand[4]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l == 10 and pc_r == 11:       
        print("ERROR 26")
        pass # can't happen
        raise SystemExit

    elif pc_l == 11 and pc_r == 0:        
        print("ERROR 27")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 1:       
        print("ERROR 28")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 10:       
        print("ERROR 29")
        pass # can't happen
        raise SystemExit
    elif pc_l == 11 and pc_r == 11:       
        print("ERROR 30")
        pass # can't happen
        raise SystemExit

    else:
        pass


if start_spot == 1 and end_spot == 3:
    if   pc_r ==  0:
        best5 = [hand[5],hand[6],hand[1],hand[2],hand[3]]
        print(hand, best5, 'trips')
        raise SystemExit
    elif pc_r ==  1:
        best5 = [hand[4],hand[5],hand[1],hand[2],hand[3]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_r ==  10:   
        best5 = [hand[5],hand[6],hand[1],hand[2],hand[3]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_r ==  11:
        best5 = [hand[2],hand[3],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    else:
        pass


if start_spot == 3 and end_spot == 5:
    if   pc_l ==  0:
        best5 = [hand[2],hand[6],hand[3],hand[4],hand[5]]
        print(hand, best5, 'trips')
        raise SystemExit
    elif pc_l ==  1:
        best5 = [hand[1],hand[2],hand[3],hand[4],hand[5]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l ==  10:   
        best5 = [hand[0],hand[1],hand[3],hand[4],hand[5]]
        print(hand, best5, 'full house')
        raise SystemExit
    elif pc_l ==  11:
        best5 = [hand[1],hand[2],hand[4],hand[5],hand[6]]
        print(hand, best5, 'full house')
        raise SystemExit

    else:
        pass


print("ERROR 99")
pass # can't happen
raise SystemExit

2 个答案:

答案 0 :(得分:1)

我相信我已经实现了您指定的算法,但是它很容易出错,所以请告诉我是否有任何问题。我几乎只进行了四个核心评估

  • 是直线吗?
  • 是冲水吗?
  • 它包含多少对k?
  • 最大的k对的大小是多少?

根据这些,我确定5张卡的特定组合可以在一系列的if语句中做出的最佳手牌,并相应地对这些卡进行排序。然后,我从一组7张纸牌中创建所有5张纸牌组合的列表,使用此逻辑确定最大/最佳手形(我重新排列得分和手形顺序以完成此操作),然后返回该手形。

from collections import Counter
from itertools import combinations

def num_of_kind(cards):
    return Counter(c[0] for c in cards)

def count_pairs(cards):
    return sum(i > 1 for i in num_of_kind(cards).values())

def largest_pair(cards):
    return max(num_of_kind(cards).values())

def is_straight(cards):
    values = [c[0] for c in cards]
    index = "A23456789TJQKA"["K" in values:].index
    indices = sorted(index(v) for v in values)
    return all(x == y for x, y in enumerate(indices, indices[0]))

def is_flush(cards):
    suit_pop = Counter(c[1] for c in cards)
    return any(s > 4 for s in suit_pop.values())

def straight_sort(cards):
    values = [c[0] for c in cards]
    index = "A23456789TJQKA"["K" in values:].index
    return sorted(cards, key=lambda x:index(x[0]), reverse=True)

def flush_sort(cards):
    suit_pop = Counter(c[1] for c in cards)
    return sorted(cards, key=lambda x: suit_pop[x[1]], reverse=True)

def pair_sort(cards):
    num = num_of_kind(cards)
    return sorted(cards, key=lambda x: num[x[0]], reverse=True)

def card_vals(cards):
    return [c[0] for c in cards]

def score_hand(cards):
    pairs = count_pairs(cards)
    largest = largest_pair(cards)
    straight = is_straight(cards)
    flush = is_flush(cards)

    cards = straight_sort(cards)
    hand_score = 0
    if flush and straight:
        hand_score, cards = 8, flush_sort(cards)
    elif largest == 4:
        hand_score, cards = 7, pair_sort(cards)
    elif pairs == 2 and largest == 3:
        hand_score, cards = 6, pair_sort(cards)
    elif flush:
        hand_score, cards = 5, flush_sort(cards)
    elif straight:
        hand_score = 4
    elif largest == 3:
        hand_score, cards = 3, pair_sort(cards)
    else:
        hand_score, cards = pairs, pair_sort(cards)
    return hand_score, card_vals(cards), cards

def best_hand(cards):
    cards = max(list(combinations(cards, 5)), key=score_hand)
    score, _, hand = score_hand(cards)
    return hand[::-1], score

def main():
    hand = ['2c','Ah','3d', '5s','4h','5d', '3h']
    print(*best_hand(hand))

if __name__ == "__main__":
    main()

我可以为您介绍每种方法的细节,但是我觉得这一切都是不言而喻的。唯一棘手的地方是is_straight(),这只是确定索引值是否可以按顺序排序的一些索引技巧。

答案 1 :(得分:0)

在设计算法以寻找最佳手牌时,您可能会考虑以下几点:

  • 所有比较均用于比较卡的价值(数量)和/或花色。因此,您可能需要考虑制作一个卡号列表和一个卡套列表。或查看itertools模块具有的技巧。
  • 同花顺是唯一重要的衣服。否则,您只查看卡号。
  • 同花顺和同花顺是您必须寻找5个连续数字的唯一手牌。请记住,这可以包括ace和面卡。另外,如果包含了一张王牌,那么它必须在开头或结尾(例如,“ Q K A 2 3”不算作直线)。您可能还需要研究模块more_itertools.consecutive_groups
  • 另一只手(一对,两对,三种,全屋,四种)全部基于出现相同数字的频率。如果一个值出现4次,则无需检查此列表中的其他指针。如果出现3次,则检查是否可以满屋,否则为3张。您可以像这样从高手到低手继续查看该列表,直到有比赛时才停止。
  • 您甚至可以考虑创建一个名为Card的类,并将您的卡片作为“卡片”类型的对象输入。然后,您可以在该类中具有一些函数来返回卡的花色或数值。