快速扑克手排名

时间:2013-11-10 11:27:29

标签: c lookup lookup-tables poker

我正在进行扑克模拟,现在我必须有效地排名:

每手牌都是5张牌的组合,代表uint64_t 从0(黑桃王牌),1(心中的王牌)到51(两个俱乐部)的每一位表示相应的牌是否是手的一部分(比特== 1)或不是部分(比特== 0) 。从52到63的位始终设置为零,并且不保存任何信息。

我已经知道理论上我是如何生成一个表的,因此每个有效的手都可以映射到1(2,3,4,5,7之间 - 不在同一个范围内的范围(表示为uint16_t)颜色)和7462(皇家同花顺)和所有其他的铃声零。

因此,一个天真的查找表(使用卡的整数值作为索引)将具有巨大大小 2 bytes * 2^52 >= 9.007 PB
大部分内存都会被零填充,因为从0到2 ^ 52-1的几乎所有uint64_t都是无效的手,因此有一个等于零的范围。
有价值的数据只占用 2 bytes * 52!/(47!*5!) = 5.198 MB

我可以使用什么方法进行映射,这样我只需要保存有效卡中的等级和一些开销(最多100 MB),但仍然不需要进行一些昂贵的搜索...... 它应该尽可能快!

如果您有任何其他想法,欢迎您! ;)

5 个答案:

答案 0 :(得分:3)

您只需要一张13 ^ 5 * 2的表格,其中包含额外的信息,指示所有卡牌是否属于同一套牌。如果出于某种原因“心脏”超过“钻石”,你最多还需要一张尺寸为13 ^ 6的桌子,因为最后一条信息编码为'0 =无图案,1 =所有黑桃,2 =所有心,等。

哈希表可能也是一种好的快速方法 - 从nCk(52,5)组合创建表并不需要花费太多时间(与所有可能的手相比)。但是,人们需要为每个条目存储65位信息,以存储密钥(52位)和秩(13位)。

加快对手的评价,先从面具中排除非法组合:
 if (popcount(mask) != 5);之后一次可以使用足够的比特来自例如crc32(mask),至少在i7架构中具有指令级支持。

答案 1 :(得分:1)

如果我正确理解你的方案,你只需要知道特定手的海明重量正好是5,因为它是一个有效的手。有关如何计算汉明重量的信息,请参阅Calculating Hamming Weight in O(1)

从那里开始,你似乎可以自己解决剩下的问题。就个人而言,我想将结果存储在一些持久性内存中(如果它在您选择的平台上可用),以便后续运行更快,因为它们不需要生成索引表。

答案 2 :(得分:0)

我想到的一个简单实现是将您的方案更改为基数52中的5位数。用于保存所有这些值的结果表仍然会比必要的大,但实现起来非常简单,它会很容易适应现代计算机上的RAM。

编辑:您还可以通过仅存储每张卡的等级和另外的标记(例如,最低位)来指定更多,以指定所有卡是否具有相同的套装(即,可以刷新)。然后,这将在基数13 +一位用于排名表示。那么你可能需要分别存储卡片的特定套装,以重建精确的显示手等。

答案 3 :(得分:0)

我会以不同的方式代表你的手: 只有4个套装= 2比特,只有13个卡= 4比特,总共6比特* 5 = 30 - 所以我们适合32比特的int - 我们也可以强迫这个按照你的订单排序

[suit 0] [suit 1] [suit 2] [suit 3] [suit 4] [value 0] [value 1] [value 2] [value 3] [value 4]

然后我会使用单独的哈希:

  • 连续性价值观(非常小)[掩盖西装]
  • 1个或更多倍数(一对,两对,满堂)[掩盖西装]
  • 适合全部相同(非常小)[掩盖价值]

然后使用3个哈希来计算你的排名 在5MB时,您可能会有足够的缓存问题,这将使数学和三个小查找更快

答案 4 :(得分:0)

这是一个很好的来源 Cactus Kev's

对于一只手,你可以利用最多4件西装 等级(0-12)为4位,套装为2位 6位* 5张卡只有30位
称之为4个字节
只有2598960手 总尺寸略小于10 mb