【问题标题】:How to return all combinations that contains a given *partial* combination?如何返回包含给定*部分*组合的所有组合?
【发布时间】:2012-06-27 18:12:32
【问题描述】:

我有这个 c# 类,它计算 n 选择 k,然后按字典顺序生成所有可能的组合。它还可以返回每个组合的订单号,例如:传递 [1,2,3,4,5] 将返回 1 给定 n 选择 k(30,5),142506 为 [26,27,28,29,30] .

有没有办法返回所有包含部分组合的订单号?因此,如果我通过 [1,2,3,4] 它将返回:1,2,3,...25,26。

1: [1,2,3,4,5]
2: [1,2,3,4,6]
3: [1,2,3,4,7]
...
25: [1,2,3,4,29]
26: [1,2,3,4,30]

我需要这个来抽奖。我希望每张票都有它的组合订单号,并且在抽取 5 个球时,我需要显示可能获胜者的总数。现在每张票都有实际的组合,我运行查询以获得部分获胜者,但我想优化这个过程。

【问题讨论】:

  • 只像往常一样生成排列,减去列表中包含的排列,然后将所述列表添加到前面?
  • (+1) 质疑公平点分配 ;)

标签: c# permutation combinations


【解决方案1】:

您需要一个函数,对于组合 [a, b, c, d, e],返回该组合的订单号。然后你可以得到组合集(可能的数字集减去已经选择的数字)选择(你还没有选择的数量),将已经选择的数字添加到每个组合中,重新排序每个组合,然后使用它获取订单号的函数。

编辑:这可能会有所帮助:saliu.com/bbs/messages/348.html

EDIT2:答案就在这里:How to calculate the index (lexicographical order) when the combination is given

EDIT3:我为此尝试了一些 C# 代码:

private IEnumerable<int[]> CombinationsFor(int n, int k);
private int CombinationsCount(int n, int k);

private int IndexFor(int n, int[] combination)
{
    int k = combination.Count();
    int ret = 0;

    int j = 0;
    for (int i = 0; i < k; i++)
    {
        for (j++; j < combination[i]; j++)
        {
            ret += CombinationsCount(n - j, k - i - 1);
        }
    }

    return ret;
}

private IEnumerable<int> PossibleCombinations(int n, int k, int[] picked)
{
    int m = picked.Count();

    int[] reverseMapping = Enumerable.Range(0, n)
        .Where(i=>!picked.Contains(i))
        .ToArray();

    return CombinationsFor(n-m, k-m)
        .Select(c => c
            .Select(x=>reverseMapping[x])
            .Concat(picked)
            .OrderBy(x=>x)
            .ToArray()
        )
        .Select(c => IndexFor(n, c));
}

【讨论】:

  • 我已经获得了计算给定组合索引的函数,但感谢您解释获得所需结果所需的逻辑。现在我不知道该接受哪个答案,你的还是 saverio 的。 :)
  • reverseMapping ;) 良好的 C# 实现 (+1)。我感谢上帝不必为我用 C# 编码支付账单:D
【解决方案2】:

您需要的组合是(n-d) choose (k-d),其中d 是固定抽奖次数。

当您生成它们时,它们不会有正确的数字(它们会跳过最后一个 d 数字而不是您想要的数字),而只是使用子列表的逆序映射重新编写您的组合:

(在伪 python 代码中,因为这根本与 C# 无关)

listing = [1, 2, ..., 30]
partial = [4, 7, 25]
draw_size = 5
remaining = listing - partial
reverse_order_mapping = [(index, item) in remaining.items_and_indexes]

n = listing.size  // 30
k = draw_size     // 5
d = partial.size  // 3

for comb in ((n-d) choose (k-d))
  actual_comb = comb.map(reverse_order_mapping)
  print actual_comb
end

然后您只需使用生成的组合调用您的函数(如果需要,在对其进行排序之后)。

【讨论】:

  • 您的回答和 Thom 的回答都帮助我了解了获取索引所需的内容,+1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多