非布尔"真值表"创建

时间:2015-02-02 23:22:02

标签: c# logic combinatorics multiset

我有以下问题:我需要创建一个表,它是来自集合的值的组合。集合中元素的基数是未知的,并且可能因设置而异,值的域未知,并且可能因设置而异。集合中的元素是非负的,集合中至少有两个元素。 以下是一个例子:

  • SET_A = {0,1,2}
  • SET_B = {0,1}
  • SET_C = {0,1}

结果应包含以下行(顺序不是约束):

TABLE:

  • | 0 0 0 |
  • | 0 0 1 |
  • | 0 1 0 |
  • | 0 1 1 |
  • | 1 0 0 |
  • | 1 0 1 |
  • | 1 1 0 |
  • | 1 1 1 |
  • | 2 0 0 |
  • | 2 0 1 |
  • | 2 1 0 |
  • | 2 1 1 |

有谁知道这个问题背后的数学是什么?我试着看看Multiset问题,逻辑表,组合。我发现的许多定义与我的问题有相似之处,但我无法隔离到目前为止我访问过的文献中的任何内容。一旦我有了参考定义,我就可以考虑编码它,但现在我迷失在递归函数和可怕的数组索引游戏中。感谢。

编辑:问题已经提出: C# Permutation of an array of arraylists?

4 个答案:

答案 0 :(得分:2)

你寻找的东西是组合学。此外,集合中元素的域是什么并不重要。只要你可以枚举它们,问题就像从0到设定基数的数字一样。

要枚举所有选项,请使用索引向量,并在每次迭代后递增第一个索引。如果溢出,则设置为0并增加第二个索引等

答案 1 :(得分:2)

编辑:抱歉,必须在昨晚运行。对于任意维度,您可能 必须使用递归。如果没有它,可能还有一种方法,但递归是最直接的。以下是未经测试但应该是正确的。

IEnumerable<int[]> getRows(int[][] possibleColumnValues, int[] rowPrefix) {
    if(possibleColumnValues.Any()) { //can't return early when using yield
        var remainingColumns = possibleColumnValues.Skip(1).ToArray();
        foreach(var val in possibleColumnValues.First()) {
           var rowSoFar = rowPrefix.Concat(new[]{val}).ToArray(); 
           yield return getRows(remainingColumns rowSoFar);
        }
    }
}

用法:

    getRows(new [][] {
                 new [] {0,1,2},
                 new [] {0,1},
                 new [] {0,1},
    }, new int[0]);

答案 2 :(得分:0)

任务是打印排列。你好像在深入挖掘它。它与元素的本质无关。

答案 3 :(得分:0)

以下内容不是为了提高效率(无论是空间还是速度)。我们的想法就是获得基本的算法。我会留给你更多的空间和时间。

基本思想是认识到n列表的所有组合,只是n-1列表的所有组合,并且第一个列表的每个元素都加上了。那时候它是一个非常简单的递归函数。

public static IEnumerable<int[]> Permute( params IEnumerable<int>[] sets )
{
    if( sets.Length == 0 ) yield break;
    if( sets.Length == 1 ) 
    {
        foreach( var element in sets[0] ) yield return new[] { element };
        yield break;
    }

    var first = sets.First();

    var rest = Permute( sets.Skip( 1 ).ToArray() );

    var elements = first.ToArray();

    foreach( var permutation in rest )
    {
        foreach( var element in elements )
        {
            var result = new int[permutation.Length + 1];
            result[0] = element;
            Array.Copy( permutation, 0, result, 1, permutation.Length );
            yield return result;
        }
    }
}