Exercise is as follows:
Generate every possible sequence whose elements are from the set {0,
1, 2} where 0 occurs m times, 1 occurs p times, and 2 occurs q times. The input file
contains three natural numbers separated by spaces, with a maximum value of 100. The solution must be written to the output file line by line
in lexicographic order. Each line should contain the elements of the series
separated by spaces.
If input is:
1 0 2
Output should be:
0 2 2
2 0 2
2 2 0
It's also stated, that I have to use recursion, and the input and output should be to .txt files.
So, I found a popular recursion for permutations which occurred on multiple sites (like this), but for some weird reason, it's not working properly for me..
The way I tried doing this exercise (there might be a smarter way) is by generating a vector from the input, and the using the permutation function with it. But my output is like this:
0 2 2
0 2 2
2 0 2
2 2 0
2 2 0
2 0 2
As you can see, every result appears twice, which is obviously not good..
Code is here below:
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
void input(int& m, int& p, int& q)
{
ifstream fin("input.txt");
fin >> m >> p >> q;
fin.close();
}
void fillVec(vector <int>& elements, int m, int p, int q)
{
fill_n(elements.begin() + m, p, 1); // filling the vectors with correct amount of numbers. The 0's all already there, so I only put the 1's, and the 2's in.
fill_n(elements.begin() + m + p, q, 2);
}
void print(const vector<int>& nums, ofstream& fout)
{
for (int a : nums) { fout << a << ' '; }
fout << endl;
}
void permute(vector<int>& nums, int n, ofstream& fout)
{
if (n == nums.size())
{
print(nums, fout);
}
else
{
for (int i = n; i < nums.size(); i++)
{
swap(nums[n], nums[i]);
permute(nums, n + 1, fout);
swap(nums[n], nums[i]);
}
}
}
int main()
{
int m, p, q;
input(m, p, q);
vector <int> elements(m + p + q);
fillVec(elements, m, p, q);
ofstream fout("output.txt");
permute(elements, 0, fout);
fout.close();
return 0;
}
I tried debugging, also looked at it multiple times to check that I copied the algorithm correctly, but can't find out what's the problem. It might be something pretty simple, I'm not sure..
Here's what I came up with. Each recursive step will attempt to append "0", "1", or "2" to the string being built until there's no available digits to add.
#include <iostream>
#include <string>
using namespace std;
void GeneratePermutations(int zeros, int ones, int twos, const string& leading)
{
if ((zeros <= 0) && (ones <= 0) && (twos <= 0))
{
// use "substr" to skip the leading space
if (leading.size() > 0)
{
std::cout << leading.substr(1) << endl;
}
return;
}
if (zeros > 0)
{
GeneratePermutations(zeros - 1, ones, twos, leading + " 0");
}
if (ones > 0)
{
GeneratePermutations(zeros, ones-1, twos, leading + " 1");
}
if (twos > 0)
{
GeneratePermutations(zeros, ones, twos-1, leading + " 2");
}
}
int main()
{
int zeros, ones, twos;
cin >> zeros;
cin >> ones;
cin >> twos;
GeneratePermutations(zeros, ones, twos, "");
return 0;
}
A couple of sample runs:
input : 1 0 2
output:
0 2 2
2 0 2
2 2 0
Another input: 3 1 1
output:
0 0 0 1 2
0 0 0 2 1
0 0 1 0 2
0 0 1 2 0
0 0 2 0 1
0 0 2 1 0
0 1 0 0 2
0 1 0 2 0
0 1 2 0 0
0 2 0 0 1
0 2 0 1 0
0 2 1 0 0
1 0 0 0 2
1 0 0 2 0
1 0 2 0 0
1 2 0 0 0
2 0 0 0 1
2 0 0 1 0
2 0 1 0 0
2 1 0 0 0
As you see and say yourself, you simply generate all possible permutations of the 0 2 2 array. There are 6 permutations for an array of length 3, and you correctly get them, but because there are two equal numbers, some of these permutations are equal.
However, apparently what you are required is to do generate only different permutations. Basically, this means that you need a new algorithm.
A simple solution may be to find a way to remove repeating permutations. There may be many approaches to it, starting with simply storing all the permutations and checking if you have already generated a given permutation, or storing the original array index with each number and requiring that the indices of equal number go in increasing order, etc. Or you can organize your recursion in a different way (that's what I would have done). Obviously the complexity of each approach will be different.
With std::next_permutation (which handles repetitions), a non recursive way would be:
void permute(std::vector<int>& nums, std::ostream& out)
{
assert(std::is_sorted(nums.begin(), nums.end()));
do {
print(nums, out);
} while (std::next_permutation(nums.begin(), nums.end()));
}
Demo
You can still transform above code in recursive way:
void permute(std::vector<int>& nums, std::ostream& out)
{
print(nums, out);
if (std::next_permutation(nums.begin(), nums.end())) { permute(nums, out); }
}
Demo
Your code is perfect and works as expected. The only problem is that your application is sometimes swapping the same digits, for example:
// nums = {0, 2, 2}
swap(nums[n], nums[i]); // n == 1, i == 2
// nums = {0, 2, 2}
Here you can notice that the application will swap 2 and 2, which will not make any difference.
Thus you can try something like this:
#include <iostream>
#include <vector>
#include <fstream>
// This std::vector will store all the elements that have been stored in output.txt
std::vector<std::string> output;
void input(int& m, int& p, int& q)
{
std::ifstream fin("input.txt");
fin >> m >> p >> q;
fin.close();
}
void fillVec(std::vector <int>& elements, int m, int p, int q)
{
fill_n(elements.begin() + m, p, 1); // filling the std::vectors with correct amount of numbers. The 0's all already there, so I only put the 1's, and the 2's in.
fill_n(elements.begin() + m + p, q, 2);
}
void print(const std::vector<int>& nums, std::ofstream& fout)
{
for (int a : nums) { fout << a << ' '; }
fout << std::endl;
}
void permute(std::vector<int>& nums, int n, std::ofstream& fout)
{
if (n == nums.size())
{
std::string num;
// Convert nums (int array) to num (std::string)
for (int i = 0; i < nums.size(); i++)
{
num.push_back(nums[i]);
}
// If same element found, return
for (int i = 0; i < output.size(); i++)
{
if (num == output[i]) return;
}
print(nums, fout);
// Insert element to output (std::vector)
output.push_back(num);
}
else
{
for (int i = n; i < nums.size(); i++)
{
std::swap(nums[n], nums[i]);
permute(nums, n + 1, fout);
std::swap(nums[n], nums[i]);
}
}
}
int main()
{
int m, p, q;
input(m, p, q);
std::vector <int> elements(m + p + q);
fillVec(elements, m, p, q);
std::ofstream fout("output.txt");
permute(elements, 0, fout);
fout.close();
return 0;
}
This code is the same as yours, except I've added a few checks to ensure that there are no duplicate elements. Now:
input.txt
1 0 2
output.txt (after application execution)
0 2 2
2 0 2
2 2 0
...which is desirable.
Also, consider removing the following statement:
using namespace std;
...as it's considered as bad practice.
Related
The input is a number n, a number m, and an array of size 3*n, whose elements are either 0s or numbers from 1 to n, where 1<=n,m<=30. I need to make an algorithm to generate the lexicographically first permutation of the set{1,...,n}, where every element appears exactly 3 times, where two equal numbers have a minimum ofm different numbers between them. Only the 0s are to be replaced, while any number that isn't 0 has to stay the same.
For example, for n=5, m=1 and the array 1 0 0 0 0 0 3 0 0 0 0 0 0 4 5 the output should be 1 2 1 2 1 2 3 4 3 5 3 4 5 4 5.
I came up with this code. It doesn't output the lexicographically first permutation. It outputs
1 2 3 4 5 1 3 2 3 4 5 1 2 4 5
#include <array>
#include <iostream>
using namespace std;
int counters[100]={3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3};
bool verify_permutation(int V[], int n, int m){
array<int,100> POZ;
POZ.fill(m);;
for(int i = 1;i<=3*n;i++){
if(V[i]==0)
return false;
for(int j = 1;j<=3*n;j++){
if(POZ[V[j]]<m)
return false;
POZ[V[j]]=0;
for(int k = 1;k<=n;k++){
POZ[k]++;
}
}
}
return true;
}
int j = 1;
void backtracking(int V[], int x, int m, int n){
if(verify_permutation(V,n,m)){
for(int i = 1;i<=3*n;i++)
cout<<V[i]<<' ';
return;
}
for(int i=1;i<=3*n;i++){
if(counters[j]==0)
continue;
if(V[i]!=0){
counters[V[i]]--;
continue;
}
j++;
if(j>n)
j=1;
if(V[i]==0){
counters[j]--;
V[i]=j;
backtracking(V,j,m,n);
counters[j]++;
}
}
return;
}
int main(){
int V[31];
int n,m;
cin>>n>>m;
if(m>=n){
cout<<-1;
return 0;
}
for(int i = 1; i <= 3*n; i++){
cin >> V[i];
}
backtracking(V, 1, m, n);
}
What is wrong with the code?
I've been struggling with a problem where based on a given number i have to find all the triplets that sum gives the given number.
For example if the given number is 5 conditions are : (x+y+z=5 and x<=y<=z) :
Input :
5
Output :
0 0 5
0 1 4
0 2 3
1 1 3
1 2 2
I've tried to find all the solutions starting with 0 but i can't figure out how to find solutions that start with 1, 2, 3, etc
What i have so far :
int x,y,z;
void showSolutions(int c) {
z=c;
while((x<=y) && (y<=z)) {
if((x<=y&&y<=z)&&(x+y+z)==c) {
cout<<x<<" "<<y<<" "<<z;
cout<<"\n";
}
y++;
z--;
}
}
Thanks for help!
Well you can think of this recursively, let me try to point a generic method which would work for two numbers or triplets or more.
class sum
{
public:
vector<vector<int>> triplets(int k, int target)
{
vector<vector<int>> result;
vector<int> holder;
getTriplets(k, target, holder, result);
return result;
}
void getTriplets(int k, int target, vector<int>& holder, vector<vector<int>>& result)
{
if(target < 0) return;
if(k < 0) return;
if(k == 0 && target == 0)
{
result.push_back(holder);
return;
}
for(int i = 0; i <= target; ++i)
{
holder.push_back(i);
getTriplets(k-1, target - i, holder, result);
holder.pop_back();
}
}
};
You can invoke this as:
sum s;
auto res = s.triplets(3,5);
for(auto row : res)
{
for(auto col : row) cout << col << " ";
cout << endl;
}
where the first argument to triplets is the what the size of set required and the latter is the garget value. The problem here is, it will produce duplicates, 0 0 5 and 5 0 0 I will leave that for you to figure out how.
Simply add results to a temporary holder and recursively try all combinations. until you reach the target value which is 0 in our case since we are subtracting, or hit a error condition. Backtrack and pop the value and exhausting all combinations. Store the result if we hit the target.
Live Demo
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int x,y,z;
for(z=n;z>=0;z--)
{
for(y=0;y<=z && z+y<=n;y++)
{
x=n-(y+z);
if(x<=y)
cout<<x<<y<<z<<endl;
}
}
}
for n=5,you get
005
014
113
023
122
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
I am trying to work out a finite element code, where I need to compute the partial derivatives in d dimension. In finite element the basis function N(x,y,z)=N(x)N(y)N(z), so the first order derivatives are:
N(x)'N(y)N(z) N(x)N(y)'N(z) N(x)N(y)N(z)'
second order derivatives are
N(x)''N(y)N(z) N(x)'N(y)'N(z) N(x)'N(y)N(z)' N(x)N(y)''N(z) N(x)N(y)N(z)' N(x)N(y)N(z)''
I want to have a functions with input (i,d) to tell me these patterns in the table below:
I think there must be a simple algorithm to realize this goal. Can someone gives me some help? THx
This can be solved with nested loops:
int * part_deriv(int i, int d){
int *res;
int *curr;
int num_el = fact(i+d-1) / ( fact(i) * fact(d-1) ); //fact() is the factorial function
int el_size = d*sizeof(int);
int el;
res = calloc(num_el,el_size);
curr = calloc(d,sizeof(int));
*curr = i;
memcpy(res,curr,el_size); //put the first element in the array
el = 0;
while(el<num_el){
if(*curr != 0){
for( d_idx = 1 ; d_idx<d ; d_idx++, *cur++){
*curr--; // "move" one derivative from the first variable to 'd_idx' variable
*(curr+d_idx)++;
el++;
memcpy(res+(el*el_size),curr,el_size); //put the element in the array
}
*curr--;
} else{
break; //shouldn't be reached, but added to be sure
}
}
return res;
}
I havn't completely understood how you want to output the result, so you can parse the array I output in blocks of d.
Consider the pattern for i'th derivative as base-i+1 integers. Nice sequences emerge. For example, in a two-dimensional case, they are
0
2, 1
6, 4, 2
12, 9, 6, 3
20, 16, 12, 8, 4
etc.
I realized it by recursive by calling a function.
#include <vector>
#include <iostream>
using namespace std;
void func (int d, int i, vector<int> &k, int n, int start, vector<vector<int>> &a){
if (n==i)
{
vector<int> m;
int it=0;
for(int it1=0;it1<d;++it1){
int amount=0;
while(find(k.begin(),k.end(),it)!= k.end()){
amount++;
it++;
}
m.push_back(amount);
it++;
}
a.push_back(m);
}
else{
for(int jj=start;jj<d+i-(i-n);++jj){
k[n]=jj;
func(d,i,k,n+1,jj+1, a
);
}
}
}
vector<vector<int>> test(int d, int i){
vector<int> kk(i);
vector<vector<int>> a;
func(d,i,kk,0,0, a);
return a;
}
int main(){
auto f = test(4,2);
for(auto it1=f.begin();it1!=f.end();++it1){
for(auto it2= it1->begin();it2!=it1->end();++it2)
cout<<*it2<<" ";
cout<<endl;
}
}
Here is my result for i=2,d=4:
2 0 0 0
1 1 0 0
1 0 1 0
1 0 0 1
0 2 0 0
0 1 1 0
0 1 0 1
0 0 2 0
0 0 1 1
0 0 0 2
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