Dynamic level of nested loops

I am trying to figure out a simple way to handle the dynamic level of nested loops. Consider the following function, which takes 2 parameters: #num loops and maximum value.

void PrintLoop(int maxloop, int maxvalue) PrintLoop(1,2); // output 0 1 PrintLoop(2,2); // output 0, 0 0, 1 1, 0 1, 1 PrintLoop(3,2); // output 0, 0, 0 0, 0, 1 0, 1, 0 0, 1, 1 1, 0, 0 1, 0, 1 1, 1, 0 1, 1, 1 

Etc ...

Is there a way to write a function that can generate the behavior of "dynamic nested loops"?

Thanks for any help

+6
c algorithm
source share
4 answers

Yes, it’s possible, and the concept of β€œ recursion :

 void PrintLoop(int maxloop, int maxvalue) { if (maxloop<=0) return ; // print something here... for (int i=0;i<maxmalue;i++){ PrintLoop(maxloop-1, maxvalue); } } 
+9
source share

Paul's answer shows how to do recursion. However, a function that takes only two arguments (the number of cycles and the maximum value) does not have enough context for the actual printing of numbers, as in your example. To do this, you will need to track additional information. One way to do this:

 void _print_loop(int *values, int width, int cur_col, int max) { if (cur_col == width) { for (int i = 0; i < width; i++) { printf("%d%c", values[i], (i < width - 1) ? ' ' : '\n'); } } else { for (int i = 0; i < max; i++) { values[cur_col] = i; _print_loop(values, width, cur_col + 1, max); } } } void print_loop(int width, int max) { int values[width]; memset(values, 0, width * sizeof(int)); _print_loop(values, width, 0, max); } 

Now print_loop(3, 2) behaves as expected.

Edit: to do this, you can write a function with two arguments, using static variables that are initialized after receiving a positive width argument. After this initialization step, the function performs its recursion using negative values. Obviously, the resulting code is terrible, but I will still send it for completeness:

 void print_loop(int width, int max) { static int max_width; static int *values; if (width > 0) { max_width = width; if ((values = calloc(width, sizeof(int))) == NULL) { perror("calloc"); exit(EXIT_FAILURE); } print_loop(-width, max); free(values); } else if (width == 0) { for (int i = 0; i < max_width; i++) { printf("%d%c", values[i], (i < max_width - 1) ? ' ' : '\n'); } } else { for (int i = 0; i < max; i++) { values[-width - 1] = i; print_loop(width + 1, max); } } } 
+5
source share

You can use recursion or you can explicitly store each state of the loop and manage the states in one loop.

In this case, this means saving an array of counters. Each execution of the main loop advances the innermost counter and all external counters whose internal neighbors are "carried over". The highest counter acts as a guard.

 void printloop(int maxloop, int maxvalue) { unsigned int counters[maxloop+1]; // C99 for the win memset(counters, 0, sizeof(counters)); while(!counters[maxloop]) { int i; char *sep=""; for(i=maxloop; i-->0;) { printf("%s%d",sep,counters[i]); sep=","; }; printf("\n"); for(i=0; counters[i]==maxvalue; i++) // inner loops that are at maxval restart at zero counters[i]=0; ++counters[i]; // the innermost loop that isn't yet at maxval, advances by 1 } } 
+3
source share

In Ada, you can make a DECLARE block after user input; then set the loop to go from 1 .. Read_In_Loop_Control_Value, and then the nested loop to print integers from 1 .. Read_In_Number_Per_Line value.

0
source share

All Articles