move zeros in an array to the end - c++

"The question comes under a broad category of "Array Transformation". This category is the meat of tech interviews. Mostly because arrays are such a simple and easy to use data structure. Traversal or representation doesn't require any boilerplate code and most of your code will look like the Pseudocode itself.
The 2 requirements of the question are:
Move all the 0's to the end of array.
All the non-zero elements must retain their original order."
My thinking:
to find the zeros and exchange their positions with the last numbers
/* int swap;
int n=nums.size()-1;
for(int i=0;i<nums.size();i--){
if(nums[i]==0){
swap = nums[i];
nums[i] = nums[n];
nums[n] = swap;
n--;
}
}
My input
[0,1,0,3,12]
Output
[1,3,12,0,0]
Diff
Expected
[1,3,12,0,0]
And I did not know why the correct answer(the part) is :
(int n = 0, cur = 0; cur < nums.size(); cur++) {
if (nums[cur] != 0) {
swap(nums[n++], nums[cur]);
}
}
}

Can you use the standard library? std::stable_partition() makes it trivial. Something like
std::stable_partition(nums.begin(), nums.end(),
[](const auto &n){ return n != 0; });
For the question of how the solution in your post works:
At the start of the first iteration, n is 0, cur is 0, and nums is [0,1,0,3,12]. nums[cur] is 0, so nothing happens. At the start of the second iteration, cur is 1, and nums[cur] is 1, so the swap and increment of n happens.
Now n is 1, cur is 2, and nums is [1,0,0,3,12]. nums[cur] is 0, so nothing happens in the third iteration. In the fourth iteration, with cur now 3, a swap happens. So at the start of the the fifth iteration, n is 2, cur is 4, and nums is [1,3,0,0,12]. I'll leave it to you to work out what happens in that step.
Basically, when n is not equal to cur, it's the index of a 0 element that can be swapped with a non-0 element that cur is the index of. This swapping eventually moves all 0's to the end.

My take on the problem, minimal std library usage. Probably not the most efficient, but it does the trick.
#include "stdafx.h"
#include <iostream>
int main()
{
int src[] = { 0, 1, 0, 3, 0, 12 }; // Output: 1 3 12 0 0 0 check
// = { 0, 3, 0, 1, 0, 0, 12, 0, 5 }; // Output: 3 1 12 5 0 0 0 0 0 check
int n = sizeof(src) / sizeof(src[0]);
for (int x = 0; x < n; x++) {
for (int y = x + 1; y < n; y++) {
if (src[x] == 0 && src[y] != 0) {
int swap = src[x];
src[x] = src[y];
src[y] = swap;
}
}
}
for (int i = 0; i < n; i++) {
std::cout << src[i] << " ";
}
return 0;
}

Related

Efficient algorithm to compute combinations with repetitions of an array adding up to given sum

So in a personal C++ project I am faced with a problem. I am rephrasing it as follows :
Given an array of n elements (e.g. [1, 3, 5], with n = 3 elements) where the number at the ith position denotes how many possible values the number at ith index can take (e.g here the first element can take 1 value which is 0; the second element can take 3 values from among 0,1,2; the third element can take 5 values from among 0,1,2,3,4).
I need to list all possible such arrays of length n that sum up to less than or equal to a given number k.
Here is an example :
Input 1:
input array = [2,2];
k = 2
Output 1:
[0,0], [0,1], [1,0], [1,1]
Also, for instance :
Input 2:
input array = [2,2];
k = 1
Output 2:
[0,0], [0,1], [1,0]
The issue :
I have coded up a simple recursive and a simple iterative solution, which enumerates all arrays and only keeps those which have sum less than k. The problem with these is that for the case where n is large and k = 1, my code takes very long to run, since it enumerates all the cases and keeps a few.
I cannot see any overlapping sub-problems so I feel DP and memoization isn't applicable. How can I write the required C++ code for this that works?
Here is my code for the iterative version :
// enumerates all arrays which sum up to k
vector<vector<int> > count_all_arrays(vector<int> input_array, int k){
vector<vector<int> > arr;
int n = (int)input_array.size();
// make auxilliary array with elements
for(int i = 0; i < n; i++){
vector<int> temp(input_array[i]);
std::iota(temp.begin(), temp.end(), 0);
arr.push_back(temp);
}
// computes combinations
vector<int> temp(n);
vector<vector<int> > answers;
vector<int> indices(n, 0);
int next;
while(1){
temp.clear();
for (int i = 0; i < n; i++)
temp.push_back(arr[i][indices[i]]);
long long int total = accumulate(temp.begin(), temp.end(), 0);
if(total <= k)
answers.push_back(temp);
next = n - 1;
while (next >= 0 &&
(indices[next] + 1 >= (int)arr[next].size()))
next--;
if (next < 0)
break;
indices[next]++;
for (int i = next + 1; i < n; i++)
indices[i] = 0;
}
return answers;
}
It's a pretty simple recursive task:
#include <bits/stdc++.h>
using namespace std;
int arr[] = {2, 2};
int n = 2;
int k = 2;
void gen(int pos, int sum, string s){
if(pos == n){
cout<<"["<<s<<" ]"<<endl;
return;
}
for(int i = 0; i < arr[pos]; i++){
if(sum + i > k) return;
gen(pos + 1, sum + i, s + " " + to_string(i));
}
}
int main(){
gen(0, 0, "");
return 0;
}
Just generate all possibilities for each slot of the array and for each choice, take the sum to the evaluation of the next slot.
When n is large and k = 1, it's natural that it takes O(n), since you will have:
[0, 0, 0, ..., 0, 0, 1]
[0, 0, 0, ..., 0, 1, 0]
[0, 0, 0, ..., 1, 0, 0]
...
[0, 0, 1, ..., 0, 0, 0]
[0, 1, 0, ..., 0, 0, 0]
[1, 0, 0, ..., 0, 0, 0]
You should use dp to make it fast in everycase. With dp[i][j] mean how many ways you use first j element to create a sum which is less than or equal i.
dp[i][j] = dp[
for (int l = 0; l <= i; l++)
dp[i][j] += dp[l][j] + min(i-l+1, input[j])
The result is dp[k,n]

Longest Consecutive Sequence in Array C++

I have to create a function that will find the longest consecutive sequence of integers in an array.
The array is this:
{1,2,3,4,4,4,5,7,9,10}
Note: repeated numbers in a sequence are skipped.
Here is my code:
int longestSequence(const int arr[], int size)
{
int currentSeq = 1;//set to 1 because all sequences are at least 1
int maxSeq;
for (int i = 1; i < size; i++)
{
if (arr[i] == arr[i-1]);//skip repeated numbers
else if (arr[i-1] == (arr[i] - 1))//check if index is 1 greater than last
{
currentSeq++;
}
else //if not reset and hold last sequence value as max
{
maxSeq = currentSeq;
currentSeq = 1;
}
}
if (currentSeq > maxSeq) //if the last index of the array was last in the sequence
{
maxSeq = currentSeq;
}
return maxSeq;
}
My code keeps returning 2 for this array but obviously it should be 5.
Any help would be appreciated.
You have 3 sequences in your array:
1, 2, 3, 4, 4, 4, 5 which has 5 consecutive numbers.
5, 7 which is not consecutive and will return 1.
7, 9 which will also return one.
9, 10 which has 2 consecutives and will return two.
In your loop you're doing this:
for (int i = 1; i < size; i++)
{
if (arr[i] == arr[i-1]);//skip repeated numbers
else if (arr[i-1] == (arr[i] - 1))//check if index is 1 greater than last
{
currentSeq++;
}
else //if not reset and hold last sequence value as max
{
maxSeq = currentSeq; // <-- You're resetting your maxSequence even if
// currentSeq is smaller.
currentSeq = 1;
}
}
Change your loop as following:
for (int i = 1; i < size; i++)
{
if (arr[i] == arr[i-1])
continue; //It is a good practice to skip the rest of the loop's
//checks if you already know you're not gonna need them.
//The continue keyword skips only the current iteration of
//the loop and improves intent readability.
else if (arr[i-1] == (arr[i] - 1))//check if index is 1 greater than last
{
currentSeq++;
}
else //if not reset and hold last sequence value as max
{
currentSeq = 1; //This line stays.
//You only want to reset it under these specific conditions.
}
if (currentSeq > maxSeq) // Now you'll get the last sequence as well.
maxSeq = currentSeq;
}
You can remove that check outside of the loop and go straight to the return. The last currentSeq will be properly registred if it is bigger than maxSeq.
Also, when I did this change I got a compile error because the new if (currentSeq > maxSeq) inside the loop tries to read maxSeq before it is ever set. So change the declaration of maxSeq to int maxSeq = 0.
With these changes I got the expected value of 5.
By running your program in a debugger with the sample array you provided, I determined that the variable currentSeq does indeed reach the value 5 and this value 5 is correctly written to maxSeq. However, later in the program, maxSeq gets overwritten by the value 1 and then 2.
Before overwriting maxSeq, you must determine whether it already contains a higher value than currentSeq. You already do this in one case, when you have reached the end of the array. But you don't do this in the other case.
For such a comparison to work, you must also initialize maxSeq, not just currentSeq. Otherwise, maxSeq may contain a very large number and always be larger than currentSeq.
#include <iostream>
void Log(int idx, int currentSeq, int maxSeq) {
printf("current[%d] = %d, max[%d] = %d\n", idx, currentSeq, idx, maxSeq);
}
int LongestSequence(int* arr, int size) {
int currentSeq = 1;
int maxSeq = 1; // max should be initialized as well
Log(0, currentSeq, maxSeq);
for (int i = 1; i < size; i++) {
if (arr[i] == arr[i - 1]) {
} else if (arr[i - 1] == (arr[i] - 1)) {
currentSeq++;
} else {
currentSeq = 1;
}
// maxSeq should be updated in time, otherwise it would be tossed away
maxSeq = std::max(maxSeq, currentSeq);
Log(i, currentSeq, maxSeq);
}
return maxSeq;
}
int main() {
int arr[] = {1, 2, 3, 4, 4, 4, 5, 7, 9, 10};
std::cout << LongestSequence(arr, sizeof(arr) / sizeof(arr[0])) << std::endl;
}
Output:
current[0] = 1, max[0] = 1
current[1] = 2, max[1] = 2
current[2] = 3, max[2] = 3
current[3] = 4, max[3] = 4
current[4] = 4, max[4] = 4
current[5] = 4, max[5] = 4
current[6] = 5, max[6] = 5
current[7] = 1, max[7] = 5
current[8] = 1, max[8] = 5
current[9] = 2, max[9] = 5
5

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

C++, not in order combination of array elements

I am trying to get all combinations of an array with C++ such that
double* list1 = new double[size];
Items in that array is {1,2,3,4,5}
I need to add all possible combinations into a stack, such as:
1+2, 1+2+3, 1+2+3+4,1+2+3+4+5, 1+3, 1+3+4, 1+3+4+5, 1+4, 1+4+5, 1+5...
the problem I am running into is I am doing this through 2 for loops and a while loop
for(int i = 0; i < size - 1; i++)
{
for(int j = i; j < size - 1; j++)
{
double temp = list1[i] + list1[j + 1];
list1combos.push(temp);
int k = j + 2;
while (k <= size - 1)
{
temp = temp + list1[k];
list1combos.push(temp);
k++;
}
}
}
I can get the ones I listed above but I have no clue how to code in combinations such as 1+3+5, or 1+2+5
Please advise on how to get those combinations, thanks stackoverflow!
Since the order does not matter, I would suggest having an array of the same size as your x and perform a binary increment on it, i.e. you start with the array inited to only 0s and count until you have only 1s. For every addition of a 1 you would pick a permutation from your x array.
First iteration:
0 0 0 0 0 -> empty
Second iteration:
0 0 0 0 1 -> you pick 5
3rd iteration:
0 0 0 1 0 -> you pick 4
4th iteration:
0 0 0 1 1 -> you pick 4 and 5
And so on until you reach:
1 1 1 1 1 -> you pick 1, 2, 3, 4 and 5
You can approach this problem by printing all subsets of a set {1,2,3,4,5}. There are 2^5 of them - or 2^5-1 since set {0) is meaningless for you.
This code can help you.
#include<iostream>
#include<list>
#include <iterator>
void print( std::list<int> l){
std::copy( l.begin(), l.end(), std::ostream_iterator<int>( std::cout, " "));
std::cout << std::endl;
}
void subset( int arr[], int size, int left, int index, std::list<int> &l){
if( left == 0){
print(l);
return;
}
for( int i = index; i < size; i++){
l.push_back( arr[i]);
subset( arr, size, left - 1, i + 1, l);
l.pop_back();
}
}
int main() {
int array[5] = { 1, 2, 3, 4, 5} ;
std::list<int> lt;
subset( array, 5, 1, 0, lt);
subset( array, 5, 2, 0, lt);
subset( array, 5, 3, 0, lt);
subset( array, 5, 4, 0, lt);
subset( array, 5, 5, 0, lt);
return 0;
}
http://ideone.com/J78J7q
more algorithms for subsets: generate all subsets of size k from a set
Others have already answered your question. I'll point out one important thing:
double* list1=new double(size);
This does not allocate an array of double with size elements.
Instead it allocates a single double and sets the value of it to size. Attempting to access it as an array results in undefined behavior and could lead to a crash.
You want to do this instead:
double* list1=new double[size];
Notice the use of square brackets. Also remember that you must call delete[] list1; instead of simply delete list1; when you want to release the allocated memory.
Following may help: http://ideone.com/SpCejs
template <std::size_t N>
bool increase(std::bitset<N>& bs)
{
for (std::size_t i = 0; i != bs.size(); ++i) {
if (bs.flip(i).test(i) == true) {
return true;
}
}
return false;
}
template <typename T, std::size_t N>
void print_combinaison(const std::array<T, N>& a)
{
std::bitset<N> bs;
do {
for (std::size_t i = 0; i != N; ++i) {
if (bs.test(i)) {
std::cout << a[i] << " ";
}
}
std::cout << std::endl;
} while (increase(bs));
}

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