1

I know the usual approach for "variable number of for loops" is said to use a recursive method. But I wonder if I could solve that without recursion and instead with using Stack, since you can bypass recursion with the use of a stack.

My example:
I have a variable number of collections and I need to combine every item of every collection with every other item of the other collections.

// example for collections A, B and C:
A (4 items) + B (8 items) + C (10 items)
4 * 8 * 10 = 320 combinations

I need to run through all those 320 combinations. Yet at compile time I don't know if B or C or D exist. How would a solution with no recursive method but with the use of an instance of Stack look like?

Edit:
I realized Stack is not necessary here at all, while you can avoid recursion with a simple int array and a few while loops. Thanks for help and info.

asked Apr 22, 2016 at 7:12
7
  • 2
    Well, technically, recursion is using the program's function call stack :p Commented Apr 22, 2016 at 7:14
  • 2
    My question would be: As a recursive method is the obvious logical choice for such a problem, why would you like to make the solution unnecessarily complicated? It's like asking "How can I add 5.5 and 4.6 using only ints?" Commented Apr 22, 2016 at 7:22
  • @phil13131 Your example is impossible. Are you saying my question asks for the impossible? I don't think so. Commented Apr 22, 2016 at 7:39
  • @user6235927 Of course it's possible to implement floating point arithmetic using integers. How do you think the early processors that didn't have FPUs did it? Commented Apr 22, 2016 at 7:47
  • @user6235927 My example is by far not impossible. You could recursively calculate every decimal digit using integers and add them up and then display it as a collection of one digit integers. High precision calculators have to work that way. It is just overly complicated for such a simple task. Commented Apr 22, 2016 at 7:47

2 Answers 2

2

Not with a stack but without recursion.

void Main()
{
 var l = new List<List<int>>()
 {
 new List<int>(){ 1,2,3 },
 new List<int>(){ 4,5,6 },
 new List<int>(){ 7,8,9 }
 };
 var result = CartesianProduct(l);
}
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
{
 IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>()};
 return sequences.Aggregate(
 emptyProduct,
 (accumulator, sequence) => 
 from accseq in accumulator 
 from item in sequence 
 select accseq.Concat(new[] {item}) 
 );
 }

Function taken form Computing a Cartesian Product with LINQ

answered Apr 22, 2016 at 7:29
3
0

Here is an example of how to do this. Algorithm is taken from this question - https://stackoverflow.com/a/2419399/5311735 and converted to C#. Note that it can be made more efficient, but I converted inefficient version to C# because it's better illustrates the concept (you can see more efficient version in the linked question):

 static IEnumerable<T[]> CartesianProduct<T>(IList<IList<T>> collections) {
 // this contains the indexes of elements from each collection to combine next
 var indexes = new int[collections.Count];
 bool done = false;
 while (!done) {
 // initialize array for next combination
 var nextProduct = new T[collections.Count];
 // fill it
 for (int i = 0; i < collections.Count; i++) {
 var collection = collections[i];
 nextProduct[i] = collection[indexes[i]];
 }
 yield return nextProduct;
 // now we need to calculate indexes for the next combination
 // for that, increase last index by one, until it becomes equal to the length of last collection
 // then increase second last index by one until it becomes equal to the length of second last collection
 // and so on - basically the same how you would do with regular numbers - 09 + 1 = 10, 099 + 1 = 100 and so on.
 var j = collections.Count - 1;
 while (true) {
 indexes[j]++;
 if (indexes[j] < collections[j].Count) {
 break;
 }
 indexes[j] = 0;
 j--;
 if (j < 0) {
 done = true;
 break;
 }
 }
 }
 }
answered Apr 22, 2016 at 8:39
1
  • I just build a function myself that does pretty much the same. Thanks! Commented Apr 22, 2016 at 9:34

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.