将一组数字池中的数字与另一组数字池的大小相匹配

本文关键字:数字 一组 | 更新日期: 2023-09-27 17:54:59

我需要通过组合其中的数字来减小集合的大小。我需要所有可能的组合。这里有两个例子可以说明我的情况。

1) Set1有4个条目,Set2有2个条目。所以我们需要在每种情况下组合两个数字。

Set1 = {70, 100, 50, 200}; Set2 = {"part1", "part2"}
All combinations I want to retrive should look like following:
"part1"        |"part2"
  70 + 100       |  50 + 200
  70 + 50        | 100 + 200
  70 + 200       |  50 + 100
 100 + 50       |  70 + 200
 100 + 200      |  50 +  70
  50 + 200       | 100 +  70
 50             |  70 + 100 + 200
 70             |  50 + 100 + 200
 100            |  50 +  70 + 200
 200            |  50 +  70 + 100  
 70 + 100 + 200 |  50
 50 + 100 + 200 |  70
 50 +  70 + 200 |  100
 50 +  70 + 100 |  200 

2) Set1有4个条目,Set2有3个条目。所以我们只需要将两个数字合并一次。

Set1 = {70, 100, 50, 200}; Set2 = {"part1", "part2", "part3"}
All combinations I want to retrive should look like following:
"part1"   |"part2"     |"part3"
   70        | 100        |  50 + 200
   70        |  50        | 100 + 200
   70        | 200        |  50 + 100
   50        |  70        | 100 + 200 
   50        | 100        |  70 + 200
   50        | 200        |  70 + 100
 100       |  70        |  50 + 200
 100       | 200        |  50 +  70
 100       |  50        | 200 +  70
 200       |  70        |  50 + 100
 200       | 100        |  50 +  70
 200       |  50        |  70 + 100
   70        |  50 + 200  |  100
   70        | 100 + 200  |   50
   70        |  50 + 100  |  200
   50        | 100 + 200  |   70
   50        | 200 + 70   |  100
   50        |  70 + 100  |  200
 100       |  50 + 200  |   70
 100       |  50 +  70  |  200
 100       | 200 +  70  |   50
 200       |  50 + 100  |   70
 200       |  50 +  70  |  100
 200       |  70 + 100  |   50 
   50 + 200  | 100        |  70
 100 + 200 |  50        |  70
   50 + 100  | 200        |  70
 100 + 200 |  70        |  50
   70 + 200  | 100        |  50
   70 + 100  | 200        |  50
   50 + 200  |  70         | 100
   50 +  70  | 200         | 100
 200 +  70 |  50         | 100
   50 + 100  |  70         | 200
   50 +  70  | 100         | 200
   70 + 100  |  50         | 200
我很感激你的帮助。我想不出任何语言来更好地解释我的担忧。但我很乐意回答任何问题。有了你的帮助,我也许能证实我的问题。虽然应用程序是用c#编写的,但并不一定需要源代码。我的问题是概念而不是实现。

提前感谢!

将一组数字池中的数字与另一组数字池的大小相匹配

好的,这里的大意是

  • {0, 0, 0, 0}开始- Set1的每个元素都是零。
  • 0表示Set2中的第一项。因此,第一个数组是"Set1中的所有内容都属于Set2中的第一项"。
  • 返回对应的分区
  • 增加{0, 0, 0, 0}{0, 0, 0, 1}
  • 1表示Set2中的第二项。因此这个数组是"Set1中的所有内容都属于Set2中的第一项,除了最后一项,它属于Set2中的第二项"。
  • 返回对应的分区
  • 增加{0, 0, 0, 1}{0, 0, 1, 0}(或{0, 0, 0, 2},如果你在Set2中有超过2个项目)。
  • 重复,直到你到达{1, 1, 1, 1}(或{2, 2, 2, 2}等),不能再走了。

然后你可以添加这样的逻辑:"如果一个分区有任何空的部分,不要麻烦它"。

我实现如下:

static IEnumerable<ILookup<T, U>> Pool<T, U>(T[] t, U[] u)
{
    // Start off with all zeroes.
    int[] indices = new int[u.Length];
    while (true)
    {
        // Build a Lookup from the array.
        var lookup = (Lookup<T,U>)indices
            .Select((ti, ui) => new { U = u[ui], T = t[ti] })
            .ToLookup(p => p.T, p => p.U);
        // Only return it if every part is non-empty.
        if (lookup.Count == t.Length)
            yield return lookup;
        // Increment to the next value.
        int toIncrement = u.Length - 1;
        while (++indices[toIncrement] == t.Length)
        {
            indices[toIncrement] = 0;
            // Stop when we can't increment further.
            if (toIncrement-- == 0)
                yield break;
        }
    }
}

可以称为

foreach (var q in Pool(
    new[] { "part1", "part2" },
    new[] { 70, 100, 50, 200 }))
{
    foreach (int i in q["part1"])
        Console.Write(i + " ");
    Console.Write("| ");
    foreach (var ii in q["part2"])
        Console.Write(ii + " ");
    Console.WriteLine();
}

注意,我把参数做成数组是因为我很懒,但是你可以把它们做成列表,或者把它们做成可枚举的,然后调用ToArray

你的问题的主要困难是:

如何得到给定集合的所有子集?

我的想法是:我想你的第一个集合不会超过32个元素。否则,结果将非常巨大。

则,对于给定的集合MySet = { a, b, c, d, e },该集合的每个子集都可以用一个介于02^5 - 1之间的值来描述。

如何?

使用位!例如,数字5 (00101二进制)表示子集中包含ac

因此,要获得给定N元素集合的子集的整个集合。只从0迭代到2^N-1,不包括。

那么,如何创建其他部分(最后一个除外)?

取第一个集合的补集,遍历它的子集。

那么,最后一部分呢?

得到你前面部分的补语!

使用此技术可能不必查找前一个子集的补集,但它需要一些非标准的位操作。