variable nested for loops

前端 未结 6 1642
南旧
南旧 2020-12-01 20:15

I\'m trying to figure out how I can use recursion to do n-level nested for loops. For example, if n=3, there would be 3 \'levels\'

for(z=0;z<6;z++){
   fo         


        
相关标签:
6条回答
  • 2020-12-01 20:23

    The basic structure of a recursive algorithm with multiple loops is as follows:

    void recursiveLoops(vector<int>& indexes, const vector<int>& endPerIndex, int currentIndex) {
        if (currentIndex == indexes.size()) {
            // This is where the real logic goes.
            // indexes[i] contain the value of the i-th index.
        } else {
            for (indexes[pos] = 0 ; indexes[pos] != endPerIndex[pos] ; indexes[pos]++) {
                // Recurse for the next level
                recursiveLoops(indexes, endPerIndex, pos+1);
            }
        }
    }
    

    The setup for calling recursiveLoops from the top level requires two vectors - one for the indexes, and one for the number of iterations at each level. The example below sets up three nested loops, iterating 5, 6, and 9 times at each level:

    vector<int> indexes(3, 0);
    vector<int> endPerIndex;
    endPerIndex.push_back(5);
    endPerIndex.push_back(6);
    endPerIndex.push_back(9);
    recursiveLoops(indexes, endPerIndex, 0);
    
    0 讨论(0)
  • 2020-12-01 20:35

    You could write it like this, but... I wouldn't. It's confusing code and doesn't give you any benefits. If you want it because your true use case has a high number of nested loops, consider just not doing that, instead; it's a serious design smell.

    void nested_loop(const int levels, const int comparator, const int level = 0, const int accumulator = 0)
    {
       if (level < levels) {
          for (int i = 0; i < 6; i++) {
             nested_loop(levels, comparator, level + 1, accumulator + i);
          }
       }
       else {
          if (accumulator == comparator) {   // your if (z+y+x==f)
             //do something
          }
       }
    }
    
    int main() {
       const int levels = 3;
       const int f = 42;
    
       nested_loop(levels, f);
    }
    

    Live demo.

    0 讨论(0)
  • 2020-12-01 20:39

    just count the depth for each recursion function, and count to f..

    void myRecursiveFunc(int depth){
       if(depth == f)
          //do something
          return;
       else{
          myRecursiveFunc(depth + 1);
       }
    }
    

    if you really want you can use three different functions for x,y and z.

    0 讨论(0)
  • 2020-12-01 20:43

    I came across this earlier today and thought I might share the solution that I eventually came up with. I'm not sure what the policy is here regarding replying to old posts. I'm just going by the fact that I came across this question this morning, and this kind of thing would have been useful to me.

    For efficiency, I've avoided recursion. Also, it doesn't use any specific c++ stuff - it will work fine on C as well.

    We're trying to create N nested "for" loops. Instead of using

    for(int i = 0; i<max; i++)
      for (int j = 0; j<max; j++)
        ...
    

    I'll be replacing i, j, ... with an array: i[0], i[1], ..., i[n-1].

    Here's my solution:

    const int n = /*Insert N here: how many loops do you need?*/;
    int i[n+1]; // if "n" is not known before hand, then this array will need to be created dynamically.
    //Note: there is an extra element at the end of the array, in order to keep track of whether to exit the array.
    
    for (int a=0; a<n+1; a++) {
      i[a]=0;
    }
    
    int MAX = 79; //That's just an example, if all of the loops are identical: e.g. "for(int i=0; i<79; i++)". If the value of MAX changes for each loop, then make MAX an array instead: (new) int MAX [n]; MAX[0]=10; MAX[1]=20;...;MAX[n-1]=whatever.
    
    int p = 0; //Used to increment all of the indicies correctly, at the end of each loop.
    while (i[n]==0) {//Remember, you're only using indicies i[0], ..., i[n-1]. The (n+1)th index, i[n], is just to check whether to the nested loop stuff has finished.
    
      //DO STUFF HERE. Pretend you're inside your nested for loops. The more usual i,j,k,... have been replaced here with i[0], i[1], ..., i[n-1].
    
    
      //Now, after you've done your stuff, we need to increment all of the indicies correctly.
      i[0]++;
      // p = 0;//Commented out, because it's replaced by a more efficient alternative below.
      while(i[p]==MAX) {//(or "MAX[p]" if each "for" loop is different. Note that from an English point of view, this is more like "if(i[p]==MAX". (Initially i[0]) If this is true, then i[p] is reset to 0, and i[p+1] is incremented.
        i[p]=0;
        i[++p]++; //increase p by 1, and increase the next (p+1)th index
        if(i[p]!=MAX)
          p=0;//Alternatively, "p=0" can be inserted above (currently commented-out). This one's more efficient though, since it only resets p when it actually needs to be reset!
      }
    }
    

    There, that's all. Hopefully the comments make it clear what it's meant to be doing. I think it should be pretty efficient - almost as much as real nested for-loops. Most of the overhead is a one-off at the beginning, so this should be more efficient that using recursive functions etc (please correct me if I'm wrong on this point).

    Hope it's useful to somebody one day.

    Peace and love.

    0 讨论(0)
  • 2020-12-01 20:44

    You are very vague about why you want this. For a starter a possible solution is to replace each for loop with a recursive function.

    void recursiveX(int zVal, int yVal, int xVal)
    {
        if(zVal+yVal+xVal == f)...
        if(xVal != 0)
            recursiveX(zVal, yVal, xVal -1);
    }
    
    void recursiveY(int zVal, int yVal)
    {
        recursiveX(zVal, yVal, 6);
        if(yVal != 0)
            recursiveY(zVal, yVal-1);
    }
    
    void recursiveZ(int val)
    {
        recursiveY(val, 6);
        if(val != 0)
            recursiveZ(val-1);
    }
    ...
    recursiveZ(6);
    

    And in the end you can merge this all into one function. Nevertheless using recursion just because it is possible is never a good Idea.

    0 讨论(0)
  • 2020-12-01 20:46

    Here's an example in plain old C++. First I make a vector of the ranges for each dimension called maxes. if the sum of all indices are 2 then I print did something. In the example I loop z from 0 to 1, y from 0 to 2, x from 0 to 3

    You can for sure make this more neat.

    Here goes:

    #include <iostream>
    #include <vector>
    using namespace std;
    
    int f(){ 
        return 2 ;
    }
    
    void inner(int depth,vector<int> & numbers,vector<int> & maxes){
      if (depth>0){
         for(int i=0;i<maxes[depth-1];i++){
            numbers[depth-1]=i;
            inner(depth-1, numbers,maxes) ;
         }
      }else{
         // calculate sum of x,y,z:
         cout << "values are ";
         for(int i=0;i<numbers.size();i++){
            cout <<numbers[i]<<" ";
         }
         int thesum(0);
         for(int i=0;i<numbers.size();i++){
            thesum+=numbers[i];
         }
         if (thesum==f()){
            cout << "did something! ";
         }
         cout<<endl;
       }
    }
    
    void donest(){
       vector<int>  numbers;
       numbers.resize(3);
       vector<int>  maxes;
       maxes.push_back(4);
       maxes.push_back(3);
       maxes.push_back(2);
       inner(numbers.size(),numbers,maxes);
    }
    
    int main(){
       donest();
    }
    

    result:

    values are 0 0 0 
    values are 1 0 0 
    values are 2 0 0  did something! 
    values are 3 0 0 
    values are 0 1 0 
    values are 1 1 0  did something! 
    values are 2 1 0 
    values are 3 1 0 
    values are 0 2 0  did something! 
    values are 1 2 0 
    values are 2 2 0 
    values are 3 2 0 
    values are 0 0 1 
    values are 1 0 1  did something! 
    values are 2 0 1 
    values are 3 0 1 
    values are 0 1 1  did something! 
    values are 1 1 1 
    values are 2 1 1 
    values are 3 1 1 
    values are 0 2 1 
    values are 1 2 1 
    values are 2 2 1 
    values are 3 2 1 
    
    0 讨论(0)
提交回复
热议问题