简体   繁体   中英

How to create a n-dimensional array of all combination of number?

I wish to create a function AllCombnations(d, maxValue) which will create a d-dimensions array of all number combinations from 0 to maxValue .

For example, a hardcoded version of creating all number combinations in 3D space, from 0 to maxValue would possibly be something like:

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

The issue I face is that I cannot nest n for loops, and am unsure how I would go about this. I have considered recursion, but have had no success. Any help would be greatly appreciated.

Actually, you can loop over dimensions. Please, have a look at Array class

Demo:

                    // [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));

Let's have a look at the array ( 20 top items):

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

Outcome:

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

I know this is an old post now, but I DID create a solution to this problem.

Let me go through this issue with an example script.

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)}");
    }
}

This is a simple enough example to show how exactly I wanted to expand on the idea of "multiple dimensions" represented as an array.

If you look to the bottom of PrintCombinations , you will see the following code:

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

This is the code I come up with the loop through multiple dimensions, removing the need to hard-code loops when you have user submitted dimensions and other information (as shown in the upper example).

Basically, this code stores the VALUE of each dimension in an array. Let us do an example of 3 dimensions, (x, y, z). We can say the point (x, y, z) = int[] { x, y, z } If we say x, y, and z are the upper bound of the array, we can loop through this array by subtracting the array's first dimesnsion, until it reaches zero, then remove one from the following dimension until it reaches zero, etc, all while resetting the dimension to the upper bound when doing so, or as in this example, add from zero to an upper bound, then reset to zero, and increment the following dimension.

By using further arrays for upper and lower bounds, you can essentially make nested loops between two specific ranges. In the above example, I used an upper bound of { 2, 2, 2, 2 } .

I hope I have explained this well. Thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM