3

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.

10
  • 1
    Please provide a small example of what you want the data to look like. Commented Nov 22, 2018 at 13:06
  • For example, something like {{0, 0, 0}, {0, 0, 1}, ..., {0, 0, maxValue}, ..., {maxValue, maxValue, maxValue}} Commented Nov 22, 2018 at 13:10
  • what do you mean by number combinations Commented Nov 22, 2018 at 13:12
  • I am working with a square/rectangular space in n-dimensions. All combinations is simply all the points within that defined space. Right now I am focusing on square spaces, so for 3D, the x, y, z coordinates all have the same region of 0->maxValue. I should note these positions are integer values. In other words, from (0,0,0) to say (10,10,10) and any number combination in between. Commented Nov 22, 2018 at 13:15
  • What would be the point of such a table? With it, you could (in this case) look up array[i, j, k] for any i, j, k, but that would just give you what you used to look it up. Commented Nov 22, 2018 at 13:15

2 Answers 2

3

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 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! I've not seen this before! I have only just picked up C# over another language, so this is advanced compared to my previous learnings, so I will look into this further. Thank you for the information!
I know this is an old post, but I posted a solution I used and was wondering if you could let me know if this is a sound solution to the problem. It's much more basic that your solution, but I thought it would be nice to have my methods confirmed correct by someone better and more experienced. Thanks.
0

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

2 Comments

Yes, your soultion is quite sound; a few improvements are: dimensions is a redundant argument; you can compute it - int dimension = startValues.Length;, to clone array - int[] loopArray = startValues.ToArray(); instead of Clone(). I suggest extracting Console.WriteLine from the method (mixing business logic and UI) and finally implementing generic method (what if I want character combinations?) as private static IEnumerable<T[]> PrintCombinations<T>(T[] startValues, T[] endValues) {..}
Thank you very much for your response. This code wasn't written very proper as it was very much code for a quick script, but those other pointers you made make good sense, and I will definitely consider them in the future! Thank you very much for your feedback!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.