如何计算特定卡组合索引

时间:2018-02-27 11:13:10

标签: c++ algorithm combinations combinatorics

52张卡牌(52 * 51 * 50 / 3! = 22100)中有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 size hash的散列函数。

3 个答案:

答案 0 :(得分:3)

有。它也很简单,我简单地想过写下怎么做,但后来我发现我需要很多数学符号。

这个想法是计算你需要一个索引之前(或之后)的组合数量。

当然,你说的52种组合中的3种是正确的。现在让我们列举一下b1,b2,b3之前的数量:

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

您现在唯一需要做的就是添加每个项目的结果,并获得索引。我建议你拿一张纸,按照建议进行数学计算,然后得到一个简单,易于评估的公式。

答案 1 :(得分:0)

如果您只想分配并获得标准套牌中任意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,而不是使用1到52,则可以使用前52个素数。

答案 2 :(得分:0)

我会忽略这样一个事实,即集合中的卡片必须是唯一的并且已经排序。然后您的索引只是card1 + 52 * card2 + 52 * 52 * card3。对于格式良好的集合,并非每个索引都可以到达,并且分布向较低的数字倾斜。尝试hash = index % prime * 52 * 52 * 52 + index均匀分发。尝试低素数。添加的索引部分确保散列将保持唯一。