Is there a way to create for-loops of a form
for(int i = 0; i < 9; ++i) {
for(int j = 0; j < 9; ++i) {
//...
for(int k = 0; k < 9; +
Here is a nice little class for a multi-index that can be iterated via a range-based for-loop:
#include<array>
template<int dim>
struct multi_index_t
{
std::array<int, dim> size_array;
template<typename ... Args>
multi_index_t(Args&& ... args) : size_array(std::forward<Args>(args) ...) {}
struct iterator
{
struct sentinel_t {};
std::array<int, dim> index_array = {};
std::array<int, dim> const& size_array;
bool _end = false;
iterator(std::array<int, dim> const& size_array) : size_array(size_array) {}
auto& operator++()
{
for (int i = 0;i < dim;++i)
{
if (index_array[i] < size_array[i] - 1)
{
++index_array[i];
for (int j = 0;j < i;++j)
{
index_array[j] = 0;
}
return *this;
}
}
_end = true;
return *this;
}
auto& operator*()
{
return index_array;
}
bool operator!=(sentinel_t) const
{
return !_end;
}
};
auto begin() const
{
return iterator{ size_array };
}
auto end() const
{
return typename iterator::sentinel_t{};
}
};
template<typename ... index_t>
auto multi_index(index_t&& ... index)
{
static constexpr int size = sizeof ... (index_t);
auto ar = std::array<int, size>{std::forward<index_t>(index) ...};
return multi_index_t<size>(ar);
}
The basic idea is to use an array that holds a number of dim
indices and then implement operator++
to increase these indices appropriately.
Use it as
for(auto m : multi_index(3,3,4))
{
// now m[i] holds index of i-th loop
// m[0] goes from 0 to 2
// m[1] goes from 0 to 2
// m[2] goes from 0 to 3
std::cout<<m[0]<<" "<<m[1]<<" "<<m[2]<<std::endl;
}
Live On Coliru
I use this solution:
unsigned int dim = 3;
unsigned int top = 5;
std::vector<unsigned int> m(dim, 0);
for (unsigned int i = 0; i < pow(top,dim); i++)
{
// What you want to do comes here
// |
// |
// v
// -----------------------------------
for (unsigned int j = 0; j < dim; j++)
{
std::cout << m[j] << ",";
}
std::cout << std::endl;
// -----------------------------------
// Increment m
if (i == pow(top, dim) - 1) break;
unsigned int index_to_increment = dim - 1;
while(m[index_to_increment] == (top-1)) {
m[index_to_increment] = 0;
index_to_increment -= 1;
}
m[index_to_increment] += 1;
}
It can certainly optimized and adapted, but it works quite well and you don't need to pass parameters to a recursive function. With a separate function to increment the multi-index:
typedef std::vector<unsigned int> ivec;
void increment_multi_index(ivec &m, ivec const & upper_bounds)
{
unsigned int dim = m.size();
unsigned int i = dim - 1;
while(m[i] == upper_bounds[i] - 1 && i>0) {
m[i] = 0;
i -= 1;
}
m[i] += 1;
}
int main() {
unsigned int dim = 3;
unsigned int top = 5;
ivec m(dim, 0);
ivec t(dim, top);
for (unsigned int i = 0; i < pow(top,dim); i++)
{
// What you want to do comes here
// |
// |
// v
// -----------------------------------
for (unsigned int j = 0; j < dim; j++)
{
std::cout << m[j] << ",";
}
std::cout << std::endl;
// -----------------------------------
// Increment m
increment_multi_index(m, t);
}
}
I'm going to take the OP at face value on the example code that was given, and assume what's being asked for is a solution that counts through an arbitrary base-10 number. (I'm basing this on the comment "Ideally I'm trying to figure out a way to loop through seperate elements of a vector of digits to create each possible number".
This solution has a loop that counts through a vector of digits in base 10, and passes each successive value into a helper function (doThingWithNumber). For testing purposes I had this helper simply print out the number.
#include <iostream>
using namespace std;
void doThingWithNumber(const int* digits, int numDigits)
{
int i;
for (i = numDigits-1; i>=0; i--)
cout << digits[i];
cout << endl;
}
void loopOverAllNumbers(int numDigits)
{
int* digits = new int [numDigits];
int i;
for (i = 0; i< numDigits; i++)
digits[i] = 0;
int maxDigit = 0;
while (maxDigit < numDigits) {
doThingWithNumber(digits, numDigits);
for (i = 0; i < numDigits; i++) {
digits[i]++;
if (digits[i] < 10)
break;
digits[i] = 0;
}
if (i > maxDigit)
maxDigit = i;
}
}
int main()
{
loopOverAllNumbers(3);
return 0;
}
You could use a recursive function:
void loop_function(/*params*/,int N){
for(int i=0;i<9;++i){
if(N>0) loop_function(/*new params*/,N-1);
}
This will call recursively to loop_function N times, while each function will iterate calling loop_function
It may be a bit harder to program this way, but it should do what you want
You can use recursive call as:
void runNextNestedFor(std::vector<int> counters, int index)
{
for(counters[index] = 0; counters[index] < 9; ++counters[index]) {
// DO
if(index!=N)
runNextNestedFor(counters, index+1);
}
}
Call it first time as:
std::vectors<int> counters(N);
runNextNestedFor(counters, 0);
You may use recursion instead with a base condition -
void doRecursion(int baseCondition){
if(baseCondition==0) return;
//place your code here
doRecursion(baseCondition-1);
}
Now you don't need to provide the baseCondition
value at compile time. You can provide it while calling the doRecursion()
method.