Convert nested C loops into a single boost index?
boost, c++, cartesian-product
Solution
There is `BOOST_PP_SEQ_FOR_EACH_PRODUCT` in Boost.Preprocessor that can do this at pre-process step.
The BOOST_PP_SEQ_FOR_EACH_PRODUCT macro repeats a macro for each cartesian product of several seqs.
But I suppose that is not what you are looking for.
If a little reusable code is ok then you can use Function Input Iterator in Boost.Iterator to generate cartesian product of given range.
Generator
class product_generator
{
public:
typedef std::vector<int> result_type;
product_generator (int lower, int upper, unsigned int repeat)
: m_lower(lower), m_upper(upper)
{
for(unsigned int i = 0; i < repeat; ++i)
{
m_iters.push_back(m_lower);
}
};
std::vector<int> operator() ()
{
for(int& i : m_iters)
{
if(++i >= m_upper)
i = m_lower;
else
break;
}
std::vector<int> res;
for(int i : m_iters)
res.push_back(i);
return res;
};
private:
int m_lower;
int m_upper;
std::vector<int> m_iters;
};
Using this generator, you can do something like:
product_generator p(lower, upper, repeat);
auto bgn = boost::make_function_input_iterator(p, (double)0);
`bgn` is the single iterator that you can loop over to generate Cartesian product of the input sequence formed by input range.
A complete working example:
#include <vector>
#include <iostream>
#include <boost/iterator/function_input_iterator.hpp>
#include <math.h>
int main ()
{
int lower = 1;
int upper = 4;
unsigned int repeat = 3;
product_generator p(lower, upper, repeat);
for(
auto bgn = boost::make_function_input_iterator(p, (double)0);
bgn != boost::make_function_input_iterator(p, pow(upper-lower, repeat));
++bgn
)
{
for(int i : *bgn)
{
std::cout << i << " ";
}
std::cout << std::endl;
}
}
Problem
I'm slowly learning `boost` and I'm trying to find a simple way to convert the following C++ snippet: ``` for(int i=-n;i<n+1;i++) { for(int j=-n;j<n+1;j++) { for(int k=-n;k<n+1;k++) { cout << i << ' ' << j << ' ' << k << endl; } } } ``` Into a single iterator that I can loop over. In my native language `python` (can I call it that?), this is a one-liner using `itertools`: ``` itrtools.product(range(-n,n+1),repeat=3) ``` A complete answer would provide a minimal working example and a link to the docs so I can RTFM.