具体卡牌组合指数如何计算

How to calculate specific cards combination index

52 张牌中的 3 张牌有 22100 种组合 (52 * 51 * 50 / 3! = 22100)

这里列举了所有这些组合:

    static const ins cards_count = 52;
    int boardId = 0;

    for (int b1 = 0; b1 < card_count; b1++)
    { 
        for (int b2 = b1 + 1; b2 < card_count; b2++)
        {
            for (int b3 = b2 + 1; b3 < card_count; b3++)
            {
               cout << boardId << endl;
               boardId++;
            }
        }
    }

是否可以编写将 b1、b2、b3 转换为 boardId 的索引器函数(不使用地图)?如果这很难,也许你可以建议一些将 b1、b2、b3 映射到 int 大小哈希的哈希函数。

有。它也非常简单,我曾短暂地想过写下如何,但后来我意识到我需要大量的数学符号。

我们的想法是计算在您需要索引的组合之前(或之后)有多少组合。

你说的52个组合中的3个当然是正确的。现在让我们枚举有多少个出现在 b1,b2,b3 之前:

  • 首先,存在所有第一张牌小于b1的组合。第一张牌有 b1 个选项(因为你从 0 开始),对于每个选项 b1_,你有 52-b1_ 选择 2 组合。因此,这个数字是上述二项式系数从 0b1-1b1_ 的总和。只需一点数学知识,您就可以推导出一个封闭的公式,而无需实际计算总和。
  • 其次,第一张牌索引b1和第二张牌索引低于b2的所有组合。这又是一个总和,但更简单。第一张卡片有一个选择 (b1),第二张卡片有 b2-b1 选项(可能差一个,在实施之前检查)。对于这些选项中的每一个(总和超过 b2_),第三张牌有 52-b2 个选项。这是对连续数字求和,得到一个闭合公式很简单(提示:从 1 开始的前 n 个数字的总和是 n*(n+1)/2,不从一开始的连续数字是从 1).
  • 开始的两个和之间的差
  • 最后,您感兴趣的是前两张牌为b1b2,第三张小于b3的组合数。这很简单,因为总和正好是 b3.

你现在唯一需要做的就是将每个项目的结果相加,你就有了你的索引。我建议您拿一张纸,按照建议进行数学计算,然后得出一个您可以实施的简单、易于评估的公式。

如果您只想从标准牌组中分配和获取一组任意 3 张不同卡片的唯一 ID,则无需计算各种组合的组合数。

让牌组中的牌分配1到52。

您可以通过编程方式执行此操作:

int getSetId (int card1, int card2, int card3){
    if (card1 == card2 || card2 == card3 || card1 == card3)
        //throw an exception
    return (card1 * card2 * card3);
}

这将为您提供所有集合组合的唯一 ID。

编辑 1:

为了防止因乘积相同而导致id重复,可以使用前52个素数代替1到52。

我会简单地忽略一个事实,即一组中的卡片必须是唯一的和排序的。那么你的索引就是card1 + 52 * card2 + 52 * 52 * card3。对于格式良好的集合,并非每个索引都是可达的,并且分布偏向于较低的数字。尝试 hash = index % prime * 52 * 52 * 52 + index 来平衡分布。试试低素数。添加的索引部分确保哈希将保持唯一。