codechef: A puzzle game - c++

problem statement:
Johnny has some difficulty memorizing the small prime numbers. So, his computer science teacher has asked him to play with the following puzzle game frequently.
The puzzle is a 3x3 board consisting of numbers from 1 to 9. The objective of the puzzle is to swap the tiles until the following final state is reached:
1 2 3
4 5 6
7 8 9
At each step, Johnny may swap two adjacent tiles if their sum is a prime number. Two tiles are considered adjacent if they have a common edge.
Help Johnny to find the shortest number of steps needed to reach the goal state.
My solution so far
#include<bits/stdc++.h>
using namespace std;
bool prime[20];
int matrix[3][3];
int solved[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9}
};
void display()
{
for(int row = 0; row<3;row++)
{
for(int col = 0;col<3;col++)
{
cout<<matrix[row][col]<<" ";
}
cout<<endl;
}
cout<<endl<<endl;
}
bool check(){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(matrix[i][j]!=solved[i][j])
return false;
}
}
return true;
}
int min(int a,int b)
{
return (a<b)?a:b;
}
void generate(){
memset(prime,true,sizeof(prime));
for(int i=2;i*i<20;i++){
if(prime[i]==true)
{
for(int j=2*i;j<20;j+=i)
prime[j]=false;
}
}
}
int getMoves(int row, int col){
if(row < 0 ||col< 0 || row>=3||col>=3){
return 0;
}
if(check()){
return 0;
}
int moves = 0;
for(int i = row-1 ; i<= row+1 ;i++)
{
for(int j = col -1 ; j<=col+1;j++)
{
if((i!=row-1&&j!=col-1)||(i!=row+1&&j!=col+1)||(i!=row+1&&j!=col-1)||(i!=row-1&&j!=col+1)){
if(prime[matrix[row][col]+matrix[i][j]]==true)
{
moves+=getMoves(i,j);
int temp;
temp = matrix[i][j];
matrix[i][j] = matrix[row][col];
matrix[row][col] = temp;
display();
}
}
}
}
return moves;
}
int Moves(){
int minMoves = INF;
for(int row = 0;row<3;row++)
{
for(int col = 0;col<3;col++)
{
int moves = getMoves(row,col);
minMoves = min(moves,minMoves);
}
}
return minMoves;
}
int main(){
generate();
int t;
cin>>t;
while(t--)
{
for(int row = 0; row<3;row++)
{
for(int col = 0;col<3;col++)
{
cin>>matrix[row][col];
}
}
}
cout<<Moves();
}
sample testcase
Input:
2
7 3 2
4 1 5
6 8 9
9 8 5
2 4 1
3 7 6
Output:
6
-1
the program keeps crashing I guess because of memory overflow issue.

if (row < 0 || col< 0 || row >= 3 || row <= 3) {
return 0;
}
The code after this part is 'not accessible' because this condition is always true (... row >= 3 || row <= 3). You probably meant to write: (... row >= 3 || col >= 3)

I'm afraid your code is completely wrong and I don't think it could by fixed without complete rewrite. For example in function getMoves() your variables i and j can acquire value -1 so you will face access violation error. Secondly you have a recursion there, but you don't change data before you invoke recursion. Let's assume you want to swap 7 and 4. In the next step (because you didn't change input) you can swap 4 and 1. But it's not a correct move, because in that time, 4 should't be there. Thirdly your function getMoves() can end in an endless loop.
In conclusion, these kinds of problem are solved quite differently. You can for exmaple use backtracking algorithm or you can use A* algorithm. You will have to evaluate your current state. Let assume the following state:
7 3 2
4 5 6
1 8 9
You can measure number of moves that the number has to do to go to its correct position. So in this case 1 has to do 2 moves, 7 has to do 2 moves, 2 has to do 1 move as well as the number 3. The value of this state is 2 + 2 + 1 + 1 = 6. It's called an heuristic function. Now you can take this function and put it in an A* algorithm, and you should see the correct result.

Related

Why does my algorthim for insertion sort return different values , when I use the same value in condition statement?

# At first case I put the temp variable to condition statement in while loop#
int tab[8]={0,1,7,8,7,6,5,2};
int n=8;
int j;
int temp;
for(int i=1;i<n;i++)
{
temp=tab[i];
j=i-1;
while(j>=0&&tab[j]>temp)
{
tab[j+1]=tab[j];
--j;
}
tab[j+1] = temp;
}
And the resault that I get is :
0 1 7 8 7 6 5 2
0 1 2 5 6 7 7 8
But on the other hand when instead I use tab[i] in condition statement in while loop
for(int i=1;i<n;i++)
{
temp=tab[i];
j=i-1;
while(j>=0&&tab[j]>tab[i])
{
tab[j+1]=tab[j];
--j;
}
tab[j+1] = temp;
}
I get this result:
0 1 7 8 7 6 5 2
0 1 7 7 6 5 2 8
And I can't find any difference between passing these values and why it behaves like that.
I think that I am using the same values.
It's mine first question on that page , be kind to me please, have a nice day
Because in first iteration of while loop if tab[j] > tab[i]
tab[j+1]=tab[j]; changes tab[i] to tab[i - 1],
So essentially your whole program in second case is equivalent to this
#include <iostream>
int main ()
{
int tab[8]={0,1,7,8,7,6,5,2};
int n=8;
int j;
int temp;
for(int i=1;i<n;i++)
{
temp=tab[i];
j=i-1;
if (tab[j]>tab[i])
{
tab[j+1]=tab[j];
--j;
}
tab[j+1] = temp;
}
for(auto&& a: tab) {
std::cout << a << " ";
}
}

C++ - power of for loop - is that possible? [duplicate]

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++){
for(y=0;y<6;y++){
for(x=0;x<6;x++){
if (z+y+x==f){
//do something
}
}
}
}
and so on.
I can't seem to figure out how I would be able to place the if loop in the last for loop and how I can access the variables of previous for loops from the if statement. I know that the question of variable nested loops has been asked alot of times, and I have looked through all of them. But none seem to help me.
Could someone present an easy way of using recursion to achieve this, keeping in mind that I'm still a beginner in c++, to point me in the right direction?
The use case is as follows:
Write a program to input the number of dice m. The program will output the total number of possible cases, the number of possible cases for each possible n and the n with the highest probability. Note: only one input m is read in. n is computed by the program
Example if user enters m=2 then program should output
The total number of possible cases is 36.
The possibilities are
2 1
3 2
4 3
.
.
.
12 1
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
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);
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
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.
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.
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.
Variable loop using while loop in "C".
Concept
Creating a 2-dimensional array (arr[level][2]) in which first element is starting, and second element is end.
x[3][2] = {{0, 10}, {5, 20}, {2, 60}};
Creating another array with starting elements.
y[3] = {0, 5, 2};
We created a second array, because during the loop we will change the first element of "x" array.
Code
#include <stdio.h>
int main(){
// bruteforce
int level = 10;
int start[10] = {0, 0, 0, 0};
int x[10][2] = {{0, 5}, {0, 5}, {0, 5}, {0, 5}};
for (int i = 1;i < level; ++i){
x[i][1] = x[i][1] + 1;
}
while(3>2){
// Your code here
//
printf("%d %d %d %d\n", x[0][0], x[1][0], x[2][0], x[3][0]);
// variable loop code
// ==== Not To Modify ====
int a = 0;
int b = 0;
for(int i = 0;i < level; ++i){
if (x[i][0] >= x[i][1])
{
if(i != level-1){
x[i][0] = start[i];
x[i+1][0] = x[i+1][0] + 1;
}else{
a = 1;
}
b = 1;
}else{
if(b == 0){
x[0][0] = x[0][0] + 1;
b = 1;
}
}
}
if(a == 1){
break;
}
}
return 0;
}
This is a late answer, but maybe it will help someone.
Here is my solution in c++ without recursive function.:
int n_loops{3}; //number of nested for loops
int loops_idx[n_loops]; //like i,j,k but in an array
for (int i = 0; i < n_loops; i++)
loops_idx[i]=0;
int max_idx[n_loops]{3,2,4}; // like in for(; i < counter ;), but the counters in an array
bool is_finished = false;
int debug_n_of_execution{0};
while (!is_finished)
{
for (; loops_idx[0]<max_idx[0]; loops_idx[0]++)
{
/*
some code with loops_idx array as i,j,k...
*/
++debug_n_of_execution;
for (int i = 0; i < n_loops; i++)
std::cout<<loops_idx[i]<<" ";
std::cout << "\n";
}
--loops_idx[0]; //to cancel last increment
//Here it will increment the last loop_idx which isn't equal to max_idx[i]-1
//eg. after first above for loop loops_idx will be (max-1, 0, 0)
//So it will be after this loop (0, 1, 0) and start from the beginning...
for (int i = 0; i < n_loops+1; i++) //+1 to know if all loops are finished
{
if (i == n_loops)
{is_finished= true; break;}
if(loops_idx[i]==max_idx[i]-1)
continue;
++loops_idx[i];
for (int j = 0; j < i; j++) //make any previous loop = 0
loops_idx[j]=0;
break;
}
}
//just to check
int debug_perfect_n_of_execution{max_idx[0]};
for (int i = 1; i < n_loops; i++)
debug_perfect_n_of_execution*= max_idx[i];
std::cout<<"Number of execution: "<<debug_n_of_execution<<" = "<<debug_perfect_n_of_execution;
assert(debug_n_of_execution==debug_perfect_n_of_execution);
std::cout << "\nTests Finished";
And here is the result:
0 0 0
1 0 0
2 0 0
0 1 0
1 1 0
2 1 0
0 0 1
1 0 1
2 0 1
0 1 1
1 1 1
2 1 1
0 0 2
1 0 2
2 0 2
0 1 2
1 1 2
2 1 2
0 0 3
1 0 3
2 0 3
0 1 3
1 1 3
2 1 3
Number of execution: 24 = 24
Tests Finished

How to fill a 2D array with Every Possible Combination? C++ Logic

I can't figure out the logic behind this one... here's what I have so far:
#include <iostream>
using namespace std;
int thearray[4][4];
int NbPos = 4;
int main() {
int i2;
int q2;
for(int i = 1; i < 4; i++) {
for(int q = 1; q < 4; q++) {
for(int c = 0; c < NbPos; c++) {
thearray[i][q] = c;
}
}
}
}
This is filling the array up to the end is still:
3 3 3
3 3 3
3 3 3
but it's doing so without hitting anywhere near every possible combination.
Ideally once it gets to:
0 0 0
0 0 0
0 0 3
the next step SHOULD be:
0 0 0
0 0 0
0 1 0
so it hits a TON of combinations. Any ideas on how to make it hit them all? I'm stumped on the logic!
with the way you're iterating over this, a 1-dimensional array would make the looping simpler. you can still mentally treat it to have rows and columns, however they are just layed out end-to-end in the code.
you could try something like this; however if you want it in a 2D format specifically that challenge is left to you ;)
#include <iostream>
using namespace std;
#define rows 4
#define columns 4
int main() {
int thearray[rows * columns] = {0};
int NbPos = 4;
int lastPos = rows * columns - 1;
while (true) {
thearray[lastPos]++;
int pos = lastPos;
while (thearray[pos] == NbPos and pos >= 1) {
thearray[pos - 1]++;
thearray[pos] = 0;
pos--;
}
bool finished = true;
for (int i = 0; i < rows * columns; i++) {
if (thearray[i] != NbPos - 1) {
finished = false;
}
}
if (finished) {
break;
}
}
for (int i = 0; i < rows * columns; i++) {
std::cout << thearray[i] << " ";
if (i % rows == rows - 1) {
cout << endl; // makes it look like a 2D array
}
}
}
It makes sense to have the final form as all 3s , since you loop every element of the array and you assign it at the end with 3 .
So the next element will only take into account the combination with the final value of the previous element (which will be 3).
Thinking in math terms, your complexity is N^3 so to speak (actually is N^2 * 4 , but since your N is 3 ...).
Your approach is wrong, since you want to find permutations, which are defined by a factorial function , not a polinomial function.
The necessary complexity for the output doesn't match the complexity of your algorithm (your algorithm is incredbily fast for the amount of output needed).
What you are looking for is backtracking (backtacking will match the complexity needed for your output).
The recursion function should be something like this (thinking on a 1D array, with 9 elements):
RecursiveGeneratePermutations(int* curArray, int curIdx)
{
if (curIDX==9)
{
for (int i=0; i<9;i++)
{
// write the array
}
} else {
curArray[curIdx]=0;
RecursiveGeneratePermutations(curIdx+1);
curArray[curIdx]=1;
RecursiveGeneratePermutations(curIdx+1);
curArray[curIdx]=2;
RecursiveGeneratePermutations(curIdx+1);
curArray[curIdx]=3;
RecursiveGeneratePermutations(curIdx+1);
}
}
Now you only need to call the function for the index 0 :
RecursiveGeneratePermutations(arrayPtr,0);
Then wait...allot :).

Brute Force Permutation Swapping

I've been working on a brute force algorithm to generate all permutations of a given set. Eventually, I want to feed each of these permutations into a nxn matrix to test if it is a valid magic square or not.
--I KNOW THAT THERE IS A WAY TO GENERATE A MAGIC SQUARE EASILY--
That is not what I want to do, though. I'm focusing on the brute force aspect of it.
For a set of 3 elements, it works wonderfully. However, once I use 4 or more elements, I lose out on a few permutations. Just from looking at the output of 4, I am missing 7 permutations.
#include <stdio.h>
#include <iostream>
using namespace std;
//ms = magic square
//n = size
void perm(int ms[], int n) {
int pivot = 0;
int index = 0;
int pivBit = 1;
int fin = 0;
int hold = 0;
//While we are not finished
while (fin == 0) {
//Incriment the index
++index;
if (index >= n) {
index = 0;
}
//if index is equal to the pivot
if (index == pivot) {
//Is this the first time visiting the pivot?
if (pivBit == 0) {
//Are we at the beginning again?
if (index == 0 && pivot == 0)
{
fin = 1;
}
pivBit = 1;
++index;
}
//Second time visiting?
else {
pivBit = 0;
++pivot;
if (pivot >= n) {
pivot = 0;
}
}
}
//If we are out of bounds
if (index >= n) {
index = 0;
}
//swap
hold = ms[index];
ms[index] = ms[pivot];
ms[pivot] = hold;
for (int i = 0; i < n; ++i) {
cout << ms[i];
if (i < n - 1) {
cout << ", ";
}
else {
cout << endl;
}
}
}
}
int main() {
cout << "Are you ready to brute force, my brother?" << endl;
//Set
int magicsquare[] = { 1, 2, 3, 4};
int size = 4;
perm(magicsquare, size);
getchar();
return 0;
}
My output is:
2 1 3 4
3 1 2 4
4 1 2 3
1 4 2 3
1 2 4 3
1 3 4 2
3 1 4 2
3 4 1 2
3 4 2 1
2 4 3 1
2 3 4 1
2 3 1 4
4 3 1 2
4 2 1 3
4 2 3 1
1 2 3 4
2 1 3 4
Looking at it, I can already see that I am missing both 1 4 3 2 and 1 3 2 4.
Where've I gone wrong in my algorithm?
The wiki article on permutation includes a common algorithm used to produce all permutations in lexicographic order, starting with an array of sequentially increasing integers, ending with that array reversed. wiki next permutation.
If dealing with an array of objects, you can generate an array of indices 0 through n-1 and use next permutation on the indices to produce all permutations of the array of objects.
You can also do a web search for next permutation to find similar algorithms. The recursive ones produce all permutations, but not in lexicographic order.
The simplest way to generate all permutations is recursive. For each i, swap the i'th element to the 0 position. Then recursively find all permutations of of the remaining array.
int buf[1000], n; // better to wrap these in a class...
void permute(int *a, int a_len) {
if (a_len == 1) {
for (int i = 0; i < n; i++) printf("%d ", buf[i]);
printf("\n");
} else {
for (int i = 0; i < a_len; i++) {
swap(a, 0, i);
permute(a + 1, a_len - 1);
swap(a, 0, i);
}
}
}
void run(int buf_len) {
for (int i = 0; i < buf_len; i++) buf[i] = i + 1;
n = buf_len;
permute(buf, buf_len);
}
This assumes no repeated elements in the original array. It's not to hard to have it take repeated elements into account.

variable nested for loops

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++){
for(y=0;y<6;y++){
for(x=0;x<6;x++){
if (z+y+x==f){
//do something
}
}
}
}
and so on.
I can't seem to figure out how I would be able to place the if loop in the last for loop and how I can access the variables of previous for loops from the if statement. I know that the question of variable nested loops has been asked alot of times, and I have looked through all of them. But none seem to help me.
Could someone present an easy way of using recursion to achieve this, keeping in mind that I'm still a beginner in c++, to point me in the right direction?
The use case is as follows:
Write a program to input the number of dice m. The program will output the total number of possible cases, the number of possible cases for each possible n and the n with the highest probability. Note: only one input m is read in. n is computed by the program
Example if user enters m=2 then program should output
The total number of possible cases is 36.
The possibilities are
2 1
3 2
4 3
.
.
.
12 1
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
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);
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
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.
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.
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.
Variable loop using while loop in "C".
Concept
Creating a 2-dimensional array (arr[level][2]) in which first element is starting, and second element is end.
x[3][2] = {{0, 10}, {5, 20}, {2, 60}};
Creating another array with starting elements.
y[3] = {0, 5, 2};
We created a second array, because during the loop we will change the first element of "x" array.
Code
#include <stdio.h>
int main(){
// bruteforce
int level = 10;
int start[10] = {0, 0, 0, 0};
int x[10][2] = {{0, 5}, {0, 5}, {0, 5}, {0, 5}};
for (int i = 1;i < level; ++i){
x[i][1] = x[i][1] + 1;
}
while(3>2){
// Your code here
//
printf("%d %d %d %d\n", x[0][0], x[1][0], x[2][0], x[3][0]);
// variable loop code
// ==== Not To Modify ====
int a = 0;
int b = 0;
for(int i = 0;i < level; ++i){
if (x[i][0] >= x[i][1])
{
if(i != level-1){
x[i][0] = start[i];
x[i+1][0] = x[i+1][0] + 1;
}else{
a = 1;
}
b = 1;
}else{
if(b == 0){
x[0][0] = x[0][0] + 1;
b = 1;
}
}
}
if(a == 1){
break;
}
}
return 0;
}
This is a late answer, but maybe it will help someone.
Here is my solution in c++ without recursive function.:
int n_loops{3}; //number of nested for loops
int loops_idx[n_loops]; //like i,j,k but in an array
for (int i = 0; i < n_loops; i++)
loops_idx[i]=0;
int max_idx[n_loops]{3,2,4}; // like in for(; i < counter ;), but the counters in an array
bool is_finished = false;
int debug_n_of_execution{0};
while (!is_finished)
{
for (; loops_idx[0]<max_idx[0]; loops_idx[0]++)
{
/*
some code with loops_idx array as i,j,k...
*/
++debug_n_of_execution;
for (int i = 0; i < n_loops; i++)
std::cout<<loops_idx[i]<<" ";
std::cout << "\n";
}
--loops_idx[0]; //to cancel last increment
//Here it will increment the last loop_idx which isn't equal to max_idx[i]-1
//eg. after first above for loop loops_idx will be (max-1, 0, 0)
//So it will be after this loop (0, 1, 0) and start from the beginning...
for (int i = 0; i < n_loops+1; i++) //+1 to know if all loops are finished
{
if (i == n_loops)
{is_finished= true; break;}
if(loops_idx[i]==max_idx[i]-1)
continue;
++loops_idx[i];
for (int j = 0; j < i; j++) //make any previous loop = 0
loops_idx[j]=0;
break;
}
}
//just to check
int debug_perfect_n_of_execution{max_idx[0]};
for (int i = 1; i < n_loops; i++)
debug_perfect_n_of_execution*= max_idx[i];
std::cout<<"Number of execution: "<<debug_n_of_execution<<" = "<<debug_perfect_n_of_execution;
assert(debug_n_of_execution==debug_perfect_n_of_execution);
std::cout << "\nTests Finished";
And here is the result:
0 0 0
1 0 0
2 0 0
0 1 0
1 1 0
2 1 0
0 0 1
1 0 1
2 0 1
0 1 1
1 1 1
2 1 1
0 0 2
1 0 2
2 0 2
0 1 2
1 1 2
2 1 2
0 0 3
1 0 3
2 0 3
0 1 3
1 1 3
2 1 3
Number of execution: 24 = 24
Tests Finished