如何创建所有数字组合的n维数组?

时间:2018-11-22 13:03:02

标签: c# arrays

我希望创建一个函数AllCombnations(d, maxValue),该函数将创建从0到maxValue的所有数字组合的d维数组。

例如,在3D空间中创建所有数字组合(从0到maxValue)的硬编码版本可能类似于:

for (int i = 0; i < maxValue; i++)
    for (int j = 0; j < maxValue; j++)
        for (int k = 0; k < maxValue; k++)
        {
            // code here
        }

我面临的问题是我无法嵌套 n进行循环,并且不确定如何处理。我考虑过递归,但没有成功。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

实际上,您可以 遍历尺寸。请看看Array

演示:

                    // [6, 6, 6] array
int rank = 3;       // 3D array - 3 dimensions
int maxValue = 6;   // Each dimension is of size 6

int[] lengths = Enumerable // {6, 6, 6} - lengths of the dimensions:
  .Repeat(maxValue, rank)  // rank times maxValue 
  .ToArray();              // materialized as array

//TODO: put the right type of arrays' items 
// In demo, let array be of type string: "string[6, 6, 6] array"
var array = Array.CreateInstance(typeof(string), lengths);

// we can't use hardcoded set (i, j, k) of variables 
// we have to address array's item via array of rank length
int[] address = new int[array.Rank];

// Single loop over all array's items (and dimensions)
do {
  //TODO: put the right value here by given address:
  //      (i == address[0], j == address[1], k == address[2] etc.)
  array.SetValue(
    string.Concat(address.Select(i => (char) (i + 'A'))), // value: "AAA", "AAB" etc. 
    address);                                             // address: [0,0,0], [0,0,1], 

  // here we compute next address
  for (int i = 0; i < address.Length; ++i)
    if (address[i] >= array.GetLength(i) - 1)
      address[i] = 0;
    else {
      address[i] += 1;
      break;
    }

  // if we get {0, 0, ..., 0} address, we've exhausted all the items
}
while (!address.All(index => index == 0));

让我们看一下数组({20个最重要的项目):

  Console.WriteLine(string.Join(Environment.NewLine, array.OfType<string>().Take(20)));

结果:

AAA
AAB
AAC
AAD
AAE
AAF
ABA
ABB
ABC
ABD
ABE
ABF
ACA
ACB
ACC
ACD
ACE
ACF
ADA
ADB

答案 1 :(得分:0)

我知道这是一篇旧文章,但是我为这个问题创建了解决方案。

让我用示例脚本解决这个问题。

class Program
{
    static void Main()
    {
        // Print all combinations from a to b, for n dimensions
        // e.g. 0000 to 2222 <- each dimension goes from 0 to 2, with 4 dimensions
        // Note that each dimension can have a unique start/end point
        // e.g. 1234 to 5678, so the 2nd dimensions is bound 2 <= x <= 6

        int dimensions = 4;
        int[] startValues = { 0, 0, 0, 0 };
        int[] endValues = { 2, 2, 2, 2 };

        PrintCombinations(startValues, endValues, dimensions);

        Console.ReadKey();
    }

    /// <summary>
    /// Prints all combinations of numbers given inputs
    /// </summary>
    /// <param name="start">Inclusive stating integers</param>
    /// <param name="end">Inclusive ending integers</param>
    /// <param name="dimensions">The number of dimensions to iterate</param>
    private static void PrintCombinations(int[] startValues, int[] endValues, int dimensions)
    {
        // Create new array to loop through without disturbing the original array
        int[] loopArray = (int[])startValues.Clone();

        // Loop through each value
        while (!Enumerable.SequenceEqual(loopArray, endValues))
        {
            // Write array to console
            Console.WriteLine($"{string.Join(", ", loopArray)}");

            // Increment array
            loopArray[0]++;

            // Check if a dimension is larger than it's maximum, then set to min, and add +1 to next dimension
            // Do not do this for last dimension, as loop will break once the final combination is met
            for (int i = 0; i < dimensions - 1; i++)
                if (loopArray[i] > endValues[i])
                {
                    loopArray[i] = startValues[i];
                    loopArray[i + 1]++;
                }
        }

        // Write final array combination  to console
        Console.WriteLine($"{string.Join(", ", loopArray)}");
    }
}

这是一个非常简单的示例,显示了我想如何精确地扩展以数组表示的“多维”的概念。

如果您查看PrintCombinations的底部,则会看到以下代码:

for (int i = 0; i < dimensions - 1; i++)
    if (loopArray[i] > endValues[i])
    {
        loopArray[i] = startValues[i];
        loopArray[i + 1]++;
    }

这是我通过多个维度提出的循环代码,当用户提交了维度和其他信息时(如上例所示),无需对循环进行硬编码。

基本上,此代码将每个维的VALUE存储在数组中。 让我们以3个维度(x,y,z)为例。 我们可以说点(x,y,z)= int [] {x,y,z} 如果说x,y和z是数组的上限,则可以通过减去数组的第一个维度来遍历该数组,直到它达到零为止,然后从后续维度中删除一个,直到达到零为止,依此类推,在这样做时将尺寸重置为上限,或者如本例所示,从零开始添加一个上限,然后重置为零,然后增加以下尺寸。

通过使用更多数组作为上限和下限,您实际上可以在两个特定范围之间进行嵌套循环。在上面的示例中,我使用了{ 2, 2, 2, 2 }的上限。

我希望我已经解释清楚了。谢谢