【问题标题】:fast poker hand ranking快速扑克手牌排名
【发布时间】:2013-11-10 11:27:28
【问题描述】:

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

每手牌是 5 张牌的组合,表示为 uint64_t
从 0(黑桃 A)、1(红心 A)到 51(梅花二)的每一位表示对应的牌是手牌的一部分(位 == 1)还是不是手牌的一部分(位 == 0) .从 52 到 63 的位总是设置为零并且不保存任何信息。

我已经知道理论上如何生成表格,以便每只有效手都可以映射到 1 之间的范围(表示为 uint16_t)(2、3、4、5、7 - 不同颜色)和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 张牌(也许全部?)...不管这 5 张牌是什么,每张牌都是有效的。如果您的手牌只有一对二,那么其他三张牌仍然是手牌的有效部分(仅在面对另一对二时才有意义)。
  • @mah 这不是有效与否的卡片,而是他描述的编码所代表的手。正如你所说,扑克手通常是 5 张牌;但是使用这种编码,您可以轻松地表示从 0 到 52 的任意数量的牌。这是 OP 所指的空间浪费。
  • 小步骤想法:让位标志存在于每套花色的 16 位边界上。 bit0-ASpades, bit1-2Spaces .... bit16-AClubs ...这可能会使花色之间的位操作更容易。
  • 位图表示很好,但并不理想。我在 github.com/ojcardlib 中使用了一个更简单的 5 整数表示,它的扑克手评估器是 5 表查找,表只有大约 1MB。

标签: c lookup lookup-tables poker


【解决方案1】:

您只需要一张 13^5*2 的表格,额外的信息级别表明所有卡片是否都花色相同。如果由于某种原因“心”的排名超过“钻石”,您最多仍需要一个大小为 13^6 的表格,因为最后一条信息编码为“0 = 无模式,1 = 所有黑桃,2 = 所有红心,等等'。

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

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

【讨论】:

  • 实际上 64 位就足够了,因为一个人可以用 51 位对手进行编码并在 13 位中进行排名。手的最后一位将被暗示——这仅在哈希冲突检测中需要。
【解决方案2】:

如果我正确理解您的方案,您只需要知道特定手的汉明权重为 5 即可成为有效手。有关如何计算汉明权重的信息,请参阅Calculating Hamming Weight in O(1)

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

【讨论】:

    【解决方案3】:

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

    对于一手牌,您最多可以利用任何花色中的 4 个
    4 位用于等级 (0-12),2 位用于套装
    6 位 * 5 张卡只有 30 位
    称它为 4 个字节
    只有2598960手
    总大小略低于 10 mb

    【讨论】:

      【解决方案4】:

      想到的一个简单实现是将您的方案更改为以 52 为基数的 5 位数字。保存所有这些值的结果表仍会比必要的大,但实现起来非常简单,并且会轻松装入现代计算机的 RAM。

      编辑:您还可以通过仅存储每张牌的等级和一个附加标志(例如,最低位)来指定是否所有牌都具有相同的花色(例如,同花是可能的)来减少更多。然后,这将以 13 为基数 + 一位用于排名表示。然后,您可能需要单独存储卡片的特定花色,以重建确切的手牌以供展示等。

      【讨论】:

      • 抱歉,这不是一个选项,因为 52^5 = 380204032 > 5.18M + 最大 100 MB。
      • @AkiSuihkonen 是的,如果我们从字面上看最大 100MB,但这听起来不像是硬限制,而且差异小于一个数量级。 (另外我必须承认,我将“max. 100 MB's”解释为复数,即 max.million_s_ of MB。)
      【解决方案5】:

      我会以不同的方式代表你的手: 只有 4 套 = 2 位,只有 13 张牌 = 4 位,总共 6 位 * 5 = 30 - 所以我们适合 32 位整数 - 我们也可以强制它始终按照您的顺序排序

      [花色 0][花色 1][花色 2][花色 3][花色 4][价值 0][价值 1][价值 2][价值 3][价值 4]

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

      • 连续值(非常小)[遮住西装]
      • 1 或更多倍数(对、2 对、满堂)[掩饰花色]
      • 相同的西装(非常小)[掩盖价值]

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-01
        • 2011-04-19
        • 2015-10-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多