首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >形成最好的扑克牌手

形成最好的扑克牌手
EN

Code Review用户
提问于 2019-04-17 04:11:17
回答 1查看 114关注 0票数 0

这个函数就是这样做的:它得到两个元组数组,每个元组有5个条目,每个=和board =。

我需要做的是检查由两个项目和三个项目组成的数组,比如组合= Hn,Hm,Bi,Bj,Bk

代码语言:javascript
复制
def check_hand(hand, board, dictionary_A, dictionary_B):

 best_hand = []
 first_int = True

 for h1 in range (0, 4):
  for h2 in range (h1+1, 5):
   for b1 in range (0, 3):
    for b2 in range (b1+1, 4):
     for b3 in range (b2+1, 5):
      hand_check = []
      hand_check.append(hand[m1])
      hand_check.append(hand[m2])
      hand_check.append(board[b1])
      hand_check.append(board[b2])
      hand_check.append(board[b3])
      hand_check = sort(hand_check) #Custom sort for my array of objects
      hand_ranks = "".join([str(hand_check[0].rank),str(hand_check[1].rank),str(hand_check[2].rank),str(hand_check[3].rank),str(hand_check[4].rank)])

      if (hand_check[0].suit == hand_check[1].suit and hand_check[1].suit == hand_check[2].suit and hand_check[2].suit == hand_check[3].suit and hand_check[3].suit == hand_check[4].suit):
       control = [dictionary_A[hand_ranks][0],dictionary_A[hand_ranks][1]]
      else:
       control = [dictionary_B[hand_ranks][0],dictionary_B[hand_ranks][1]]

      if first_int:
       best_hand = hand_check
       rank = control
       first_int = False
      elif (int(control[0]) > int(rank[0])):
       rank = control
       best_hand = hand_check       
      elif (int(control[0]) == int(rank[0])):
       if (int(control[1]) > int(rank[1])):       
        rank = control
        best_hand = hand_check      

 return best_hand, rank[0]

我需要对两百万个不同的手进行检查,每只手的交互次数超过1000次(理想情况下,每只手至少运行100000次,以获得更准确的统计结果)。关于如何提高效率,有什么想法吗?

示例:为了更好地理解,我在路上添加了一些“打印”:

手: Q♥K♥Q♠K♠3♦︎板:2♣2♥♦︎6♥4♦︎

2♣2♥J♦︎♥K♥-2♣2♥6♥♥K♥- 2♣2♥4♦︎Q♥K♥-2♣6♣J♦︎Q♥-2♥J Q 2-2 4 64♦︎6♥J♦︎Q♥K♥-2♣2♥♦︎Q♥q♠2♣2♥6♥Q♥Q♠-2♣2♣2♥Q♥q♠6♥J Q 2♥q-2 J-2 4♠-2♥4♦︎6♥♥q♠- 4♦︎6♥J♦︎Q♥Q♠- 2♣2♥J♦︎Q♥K♠-2♣2♦︎6♣Q♥K-2♣2 4 Q-2 6 J J♥K♠-2♥4♦︎♦︎q♥K♠-2♥4♦︎6♥♥K♠- 4♦︎6♥J♦︎Q♥K♠-2♦︎J♦︎Q♥K♠2♠22♣3♦︎4♦︎6♥Q♥- 2♥3♦︎6♥J♦︎Q♥- 2♥3♦︎4♦︎J♦︎Q♥-2♦︎J♦︎q♥-2♥6♦︎6♦︎q-4♦︎6♦︎6♦︎q,J 2 2-2 6♠K♥-2♣4♦︎♦︎q♠K♥-2♣4♦︎6♥♠K♥- 2♥6♥J♦︎Q♠K♥-2♦︎Q K♥-2♦︎Q K-2♥4-6 Q0 K♦︎K♥K♠- 2♣6♥J♦︎K♥K♠-2♣4♦︎2♣2♥3♦︎6♥K♥2♣2♥3♦︎4♦︎K♥2♣6♦︎6♥J♦︎K♥-2♣3♣3♦︎K♥-2♦︎4♦︎6 K-2 6 K-2 K2︎6♥J♦︎K♥-2♣2♥♦︎Q♠K♠- 2♣2♥6♥Q♠K♠-2♣2♣2♥4♥K♣-2 J-2 K-2 4♥4♦︎6♥Q♠K♠-4♦︎6♥J♦︎♠K♠- 2♣2♥3♦︎J♦︎Q♠-2♣2♥3♥6♥q-2♥3♥J♦︎Q♠- 2♥3♦︎4♦︎J♦︎Q♠- 2♥3♦︎4♦︎6♥Q♠-3♦︎4♦︎4♦︎6♥J♦︎Q♠-2♥K-2 2 2 3D 3 KK♠- 2♣3♦︎4♦︎6♥K♠- 2♥3♦︎6♥J♦︎K♠- 2♥3♦︎4♦︎J♦︎K♠-2♥3♦︎4♦︎4♦︎6 K裂-3♣6♦︎6,J♥K♠-2♥3♦︎4♦︎J♦︎K♠

最佳手: 2♣2♥J♦︎K♥K♠排名:3

只是想知道是否有一种方法可以更有效地运行下面的代码。我刚刚开始熟悉并行程序,并认为这可能是一个答案?但我不知道如何使用imap或进程。

EN

回答 1

Code Review用户

发布于 2019-04-17 09:04:09

对于范围内的h1 (0,4):对于h2在范围内(h1+1,5):对于范围内的b1 (0,3):对于在范围内的b2 (b1+1,4):对于在范围内的b3 (b2+1,5):hand_check = [] hand_check.append(hand) hand_check.append(hand) hand_check.append(board) hand_check.append(board) hand_check.append(board) hand_check.append(Board)

在这种情况下使用itertools

代码语言:javascript
复制
for h in itertools.combinations(hand, 2):
  for b in itertools.combinations(board, 3):
    hand_check = list(h) + list(b)

而且,我不认为hand_check是一个有用的名字。通常,我希望变量名是名词(除非它们是布尔人,当谓词有意义时),当我将hand_check解析为名词时,我发现它是由hand修改的check。最小的更改是将它重命名为hand_to_check;我更喜欢candidate_hand

if (hand\_check[0].suit == hand\_check[1].suit and hand\_check[1].suit == hand\_check[2].suit and hand\_check[2].suit == hand\_check[3].suit and hand\_check[3].suit == hand\_check[4].suit):

呃。使用set

代码语言:javascript
复制
if len(set(card.suit for card in hand_check)) == 1:

hand\_check = sort(hand\_check) #Custom sort for my array of objects hand\_ranks = "".join([str(hand\_check[0].rank),str(hand\_check[1].rank),str(hand\_check[2].rank),str(hand\_check[3].rank),str(hand\_check[4].rank)]) control = [dictionary\_A[hand\_ranks][0],dictionary\_A[hand\_ranks][1]] else: control = [dictionary\_B[hand\_ranks][0],dictionary\_B[hand\_ranks][1]]

首先,为什么要进行四次查找?好呀

代码语言:javascript
复制
lookup_table = dictionary_A if only_one_suit else dictionaryB
control = lookup_table[hand_ranks]

其次,虽然Python的字符串操作非常快,但由于您的目标是进行微优化,所以您应该从整数而不是字符串的角度来考虑。我会深入研究完美散列的迷人世界,试图获得一个适合于L2缓存的查找表,甚至可能是幸运的L1 (只有6188个5级的多个集合,因此查找表不足25 kB就足够了)。

if first\_int: best\_hand = hand\_check rank = control first\_int = False elif (int(control[0]) > int(rank[0])): rank = control best\_hand = hand\_check elif (int(control[0]) == int(rank[0])): if (int(control[1]) > int(rank[1])): rank = control best\_hand = hand\_check

如果您将rank初始化为[-1],那么您应该能够消除first_int并将其简化为

代码语言:javascript
复制
      if (control > rank):
        rank = control
        best_hand = hand_check       

现在,我已经讨论了上面的微观优化,但是优化的第一条规则是从算法开始。

我需要做的是检查由两个项目和三个项目组成的所有数组,比如组合= Hn,Hm,Bi,Bj,Bk,然后我需要将每一个组合与字典进行比较

是错的。你需要做的是找出5张牌,由2张牌和3张牌组成,得分最高。

我建议您对重大重组进行微观优化,然后以以下大纲为基准:

代码语言:javascript
复制
for suit in the_four_suits:
  hand_mask = build_mask((card for card in hand if card.suit == suit))
  board_mask = build_mask((card for card in board is card.suit == suit))
  check_royal_flush(hand_mask, board_mask)
  check_straight_flush(hand_mask, board_mask)
  check_flush(hand_mask)

hand_counts = count_by_ranks(hand)
board_counts = count_by_ranks(board)
check_four_of_a_kind(hand_counts)
check_full_house(hand_counts)
...

关键的想法是做一切与位操作,并尽快返回,一旦你知道,进一步的检查将产生比你已经找到的最好的手。对于count_by_ranks,如果每个秩分配三位,那么溢出进入下一个等级是不可能的,因为只有四套西装。因此,例如检查四种类型的:

代码语言:javascript
复制
total_counts = hand_counts + board_counts
possible_fours = total_counts & 0x4924924924
# possible_fours indicates ranks where we have all four cards between hand and board
# We take three cards from board, so rule out ranks where all four are in the board
possible_fours &= ~board_counts
# Similarly, rule out ranks where all four are in hand
possible_fours &= ~hand_counts
# And rule out ranks where three are in hand
possible_fours &= ~((hand_counts << 1) & (hand_counts << 2))
if possible_fours != 0:
  # We have a four-of-a-kind: just need to extract it
票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/217597

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档