Fill vector using function specified by enum - c++

The functionality that I want is like:
std::vector<float> GetFuncVec(int N, FuncType type)
{
std::vector<float> fn(N);
float tmp = (N - 1) / 2.0;
switch (type) {
case SIN:
for (int i=0; i<N; ++i)
fn[i] = sin(M_PI * i / tmp);
break;
case SINC:
for (int i=0; i<N; ++i)
fn[i] = sin(M_PI * i / tmp) / (M_PI * i / tmp);
break;
...
}
return fn;
}
I find this unsatisfactory because there is a lot of code duplication. Looking around, I found the STL algorithm std::generate() which can fill a vector using a functor, which can have an increment member to play the role of i.
I see two potential routes. The first is to use a factory to initialize the functor. The problem with this method is code separation (above, the different cases are kept nicely together) and increased overheads with multiple new classes needed.
The second is to use lambda functions (which I have very little experience with). This is nice because I can define each function in a single line in the switch statement. But I don't see how I can avoid a scoping problem (the lambda function is not accessible outside the scope of the switch statement).
Is there a solution using lambda functions? What is the best option, from an efficiency viewpoint and from a readability viewpoint?

Maybe you want something like this...? (see it run here
#include <iostream>
#include <vector>
#include <cmath>
#include <functional>
enum Func { Sin, Sinc };
std::vector<float> f(int n, Func func)
{
std::vector<float> results(n);
float tmp = (n - 1) / 2.0;
int i;
std::function<float()> fns[] = {
[&] { return sin(M_PI * i / tmp); },
[&] { return sin(M_PI * i / tmp) / (M_PI * i / tmp); }
};
auto& fn = fns[func];
for (i=0; i<n; ++i)
results[i] = fn();
return results;
}
int main()
{
std::vector<float> x = f(10, Sin);
for (auto& v : x) std::cout << v << ' '; std::cout << '\n';
std::vector<float> y = f(10, Sinc);
for (auto& v : y) std::cout << v << ' '; std::cout << '\n';
}
Output:
0 0.642788 0.984808 0.866025 0.34202 -0.34202 -0.866025 -0.984808 -0.642788 -2.44929e-16
-nan 0.920725 0.705317 0.413497 0.122477 -0.0979816 -0.206748 -0.201519 -0.115091 -3.89817e-17

One option that may not be fast (there is indirection on each function call) but that would be a bit more flexible would be to create an std::map<FuncType, std::function<float(int,float)>>. You can't use std::generate() because you need the argument i to calculate the result, but writing your own is not that hard:
template <typename Iterator, typename Generator, typename Index, typename... Args>
void generate_i(Iterator first, Iterator last, Generator gen, Index i, Args... args)
{
while (first != last) {
*first = gen(i, args...);
++i;
++first;
}
}
Now that we have this, we need to populate a map of functors:
using FuncTypeFunction = std::function<float(int,float)>;
using FuncTypeFunctionMap = std::map<FuncType, FuncTypeFunction>;
FuncTypeFunctionMap create_functype_map()
{
FuncTypeFunctionMap functions;
functions[SIN] = [] (int i, float tmp) {
return sin(M_PI * i / tmp);
};
functions[SINC] = [] (int i, float tmp) {
return sin(M_PI * i / tmp) / (M_PI * i / tmp);
};
// ...
return functions;
}
FuncTypeFunctionMap const FuncTypeFunctions = create_functype_map();
(If you prefer you can use boost.assign to improve readability of this bit.)
And finally, we can use this map:
std::vector<float> GetFuncVec(int N, FuncType type)
{
std::vector<float> fn(N);
float tmp = (N - 1) / 2.0;
auto func = FuncTypeFunctions.find(type);
if (func != FuncTypeFunctions.end()) {
generate_i(fn.begin(), fn.end(), func->second, 0, tmp);
}
return fn;
}
Adding new functions only requires populating the map in create_functype_map(). Note that each iteration in the generate_i() loop is going to invoke the operator() on std::function, which will require a level of indirection to resolve the call, similar to the overhead of a virtual method invocation. This will cost a bit in terms of performance but may not be an issue for you.
(See a demo)

You may write a general class that will be used in standard algorithm std::iota
For example
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
class Value
{
public:
Value() : i( 0 ), fn( []( size_t i ) { return ( float )i; } ) {}
Value & operator ++() { ++i; return *this; }
operator float () const { return fn( i ); }
Value & operator =( std::function<float( size_t )> fn )
{
this->fn = fn;
return *this;
}
private:
size_t i;
std::function<float( size_t )> fn;
};
enum E { First, Second };
std::vector<float> f( size_t N, E e )
{
Value value;
float tmp = N / 2.0f;
switch( e )
{
case First:
value = [tmp] ( size_t i ) { return i * tmp; };
break;
case Second:
value = [tmp] ( size_t i ) { return i * tmp + tmp; };
break;
}
std::vector<float> v( N );
std::iota( v.begin(), v.end(), value );
return v;
}
int main()
{
for ( float x : f( 10, First ) ) std::cout << x << ' ';
std::cout << std::endl;
for ( float x : f( 10, Second ) ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
The output is
0 5 10 15 20 25 30 35 40 45
5 10 15 20 25 30 35 40 45 50
Of course you may use your own lambda expressions that include some mathematical functions like sin

Related

How can I generate the cartesian product of some vectors, whose number is given at runtime in C++? [duplicate]

I've a vector of vectors say vector<vector<int> > items of different sizes like as follows
1,2,3
4,5
6,7,8
I want to create combinations in terms of Cartesian product of these vectors like
1,4,6
1,4,7
1,4,8
and so on till
3,5,8
How can I do that ? I've looked up several links and I've also listed them at the end of this post but I'm not able to interpret that as I'm not that familiar with the language. Could some body help me with this.
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
vector<vector<int> > items;
int k = 0;
for ( int i = 0; i < 5; i++ ) {
items.push_back ( vector<int>() );
for ( int j = 0; j < 5; j++ )
items[i].push_back ( k++ );
}
cartesian ( items ); // I want some function here to do this.
}
This program has equal length vectors and I put this so that it will be easier to understand my data structure. It will be very helpful even if somebody uses others answers from other links and integrate with this to get the result. Thank you very much
Couple of links I looked at
one
Two
Program from : program
First, I'll show you a recursive version.
// Cartesion product of vector of vectors
#include <vector>
#include <iostream>
#include <iterator>
// Types to hold vector-of-ints (Vi) and vector-of-vector-of-ints (Vvi)
typedef std::vector<int> Vi;
typedef std::vector<Vi> Vvi;
// Just for the sample -- populate the intput data set
Vvi build_input() {
Vvi vvi;
for(int i = 0; i < 3; i++) {
Vi vi;
for(int j = 0; j < 3; j++) {
vi.push_back(i*10+j);
}
vvi.push_back(vi);
}
return vvi;
}
// just for the sample -- print the data sets
std::ostream&
operator<<(std::ostream& os, const Vi& vi)
{
os << "(";
std::copy(vi.begin(), vi.end(), std::ostream_iterator<int>(os, ", "));
os << ")";
return os;
}
std::ostream&
operator<<(std::ostream& os, const Vvi& vvi)
{
os << "(\n";
for(Vvi::const_iterator it = vvi.begin();
it != vvi.end();
it++) {
os << " " << *it << "\n";
}
os << ")";
return os;
}
// recursive algorithm to to produce cart. prod.
// At any given moment, "me" points to some Vi in the middle of the
// input data set.
// for int i in *me:
// add i to current result
// recurse on next "me"
//
void cart_product(
Vvi& rvvi, // final result
Vi& rvi, // current result
Vvi::const_iterator me, // current input
Vvi::const_iterator end) // final input
{
if(me == end) {
// terminal condition of the recursion. We no longer have
// any input vectors to manipulate. Add the current result (rvi)
// to the total set of results (rvvvi).
rvvi.push_back(rvi);
return;
}
// need an easy name for my vector-of-ints
const Vi& mevi = *me;
for(Vi::const_iterator it = mevi.begin();
it != mevi.end();
it++) {
// final rvi will look like "a, b, c, ME, d, e, f"
// At the moment, rvi already has "a, b, c"
rvi.push_back(*it); // add ME
cart_product(rvvi, rvi, me+1, end); add "d, e, f"
rvi.pop_back(); // clean ME off for next round
}
}
// sample only, to drive the cart_product routine.
int main() {
Vvi input(build_input());
std::cout << input << "\n";
Vvi output;
Vi outputTemp;
cart_product(output, outputTemp, input.begin(), input.end());
std::cout << output << "\n";
}
Now, I'll show you the recursive iterative version that I shamelessly stole from #John :
The rest of the program is pretty much the same, only showing the cart_product function.
// Seems like you'd want a vector of iterators
// which iterate over your individual vector<int>s.
struct Digits {
Vi::const_iterator begin;
Vi::const_iterator end;
Vi::const_iterator me;
};
typedef std::vector<Digits> Vd;
void cart_product(
Vvi& out, // final result
Vvi& in) // final result
{
Vd vd;
// Start all of the iterators at the beginning.
for(Vvi::const_iterator it = in.begin();
it != in.end();
++it) {
Digits d = {(*it).begin(), (*it).end(), (*it).begin()};
vd.push_back(d);
}
while(1) {
// Construct your first product vector by pulling
// out the element of each vector via the iterator.
Vi result;
for(Vd::const_iterator it = vd.begin();
it != vd.end();
it++) {
result.push_back(*(it->me));
}
out.push_back(result);
// Increment the rightmost one, and repeat.
// When you reach the end, reset that one to the beginning and
// increment the next-to-last one. You can get the "next-to-last"
// iterator by pulling it out of the neighboring element in your
// vector of iterators.
for(Vd::iterator it = vd.begin(); ; ) {
// okay, I started at the left instead. sue me
++(it->me);
if(it->me == it->end) {
if(it+1 == vd.end()) {
// I'm the last digit, and I'm about to roll
return;
} else {
// cascade
it->me = it->begin;
++it;
}
} else {
// normal
break;
}
}
}
}
Here is a solution in C++11.
The indexing of the variable-sized arrays can be done eloquently with modular arithmetic.
The total number of lines in the output is the product of the sizes of the input vectors. That is:
N = v[0].size() * v[1].size() * v[2].size()
Therefore the main loop has n as the iteration variable, from 0 to N-1. In principle, each value of n encodes enough information to extract each of the indices of v for that iteration. This is done in a subloop using repeated modular arithmetic:
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void cartesian( vector<vector<int> >& v ) {
auto product = []( long long a, vector<int>& b ) { return a*b.size(); };
const long long N = accumulate( v.begin(), v.end(), 1LL, product );
vector<int> u(v.size());
for( long long n=0 ; n<N ; ++n ) {
lldiv_t q { n, 0 };
for( long long i=v.size()-1 ; 0<=i ; --i ) {
q = div( q.quot, v[i].size() );
u[i] = v[i][q.rem];
}
// Do what you want here with u.
for( int x : u ) cout << x << ' ';
cout << '\n';
}
}
int main() {
vector<vector<int> > v { { 1, 2, 3 },
{ 4, 5 },
{ 6, 7, 8 } };
cartesian(v);
return 0;
}
Output:
1 4 6
1 4 7
1 4 8
...
3 5 8
Shorter code:
vector<vector<int>> cart_product (const vector<vector<int>>& v) {
vector<vector<int>> s = {{}};
for (const auto& u : v) {
vector<vector<int>> r;
for (const auto& x : s) {
for (const auto y : u) {
r.push_back(x);
r.back().push_back(y);
}
}
s = move(r);
}
return s;
}
Seems like you'd want a vector of iterators which iterate over your individual vector<int>s.
Start all of the iterators at the beginning. Construct your first product vector by pulling out the element of each vector via the iterator.
Increment the rightmost one, and repeat.
When you reach the end, reset that one to the beginning and increment the next-to-last one. You can get the "next-to-last" iterator by pulling it out of the neighboring element in your vector of iterators.
Continue cycling through until both the last and next-to-last iterators are at the end. Then, reset them both, increment the third-from-last iterator. In general, this can be cascaded.
It's like an odometer, but with each different digit being in a different base.
Here's my solution. Also iterative, but a little shorter than the above...
void xp(const vector<vector<int>*>& vecs, vector<vector<int>*> *result) {
vector<vector<int>*>* rslts;
for (int ii = 0; ii < vecs.size(); ++ii) {
const vector<int>& vec = *vecs[ii];
if (ii == 0) {
// vecs=[[1,2],...] ==> rslts=[[1],[2]]
rslts = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) {
vector<int>* v = new vector<int>;
v->push_back(vec[jj]);
rslts->push_back(v);
}
} else {
// vecs=[[1,2],[3,4],...] ==> rslts=[[1,3],[1,4],[2,3],[2,4]]
vector<vector<int>*>* tmp = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) { // vec[jj]=3 (first iter jj=0)
for (vector<vector<int>*>::const_iterator it = rslts->begin();
it != rslts->end(); ++it) {
vector<int>* v = new vector<int>(**it); // v=[1]
v->push_back(vec[jj]); // v=[1,3]
tmp->push_back(v); // tmp=[[1,3]]
}
}
for (int kk = 0; kk < rslts->size(); ++kk) {
delete (*rslts)[kk];
}
delete rslts;
rslts = tmp;
}
}
result->insert(result->end(), rslts->begin(), rslts->end());
delete rslts;
}
I derived it with some pain from a haskell version I wrote:
xp :: [[a]] -> [[a]]
xp [] = []
xp [l] = map (:[]) l
xp (h:t) = foldr (\x acc -> foldr (\l acc -> (x:l):acc) acc (xp t)) [] h
Since I needed the same functionality, I implemented an iterator which computes the Cartesian product on the fly, as needed, and iterates over it.
It can be used as follows.
#include <forward_list>
#include <iostream>
#include <vector>
#include "cartesian.hpp"
int main()
{
// Works with a vector of vectors
std::vector<std::vector<int>> test{{1,2,3}, {4,5,6}, {8,9}};
CartesianProduct<decltype(test)> cp(test);
for(auto const& val: cp) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
// Also works with something much less, like a forward_list of forward_lists
std::forward_list<std::forward_list<std::string>> foo{{"boo", "far", "zab"}, {"zoo", "moo"}, {"yohoo", "bohoo", "whoot", "noo"}};
CartesianProduct<decltype(foo)> bar(foo);
for(auto const& val: bar) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
}
The file cartesian.hpp looks like this.
#include <cassert>
#include <limits>
#include <stdexcept>
#include <vector>
#include <boost/iterator/iterator_facade.hpp>
//! Class iterating over the Cartesian product of a forward iterable container of forward iterable containers
template<typename T>
class CartesianProductIterator : public boost::iterator_facade<CartesianProductIterator<T>, std::vector<typename T::value_type::value_type> const, boost::forward_traversal_tag>
{
public:
//! Delete default constructor
CartesianProductIterator() = delete;
//! Constructor setting the underlying iterator and position
/*!
* \param[in] structure The underlying structure
* \param[in] pos The position the iterator should be initialized to. std::numeric_limits<std::size_t>::max()stands for the end, the position after the last element.
*/
explicit CartesianProductIterator(T const& structure, std::size_t pos);
private:
//! Give types more descriptive names
// \{
typedef T OuterContainer;
typedef typename T::value_type Container;
typedef typename T::value_type::value_type Content;
// \}
//! Grant access to boost::iterator_facade
friend class boost::iterator_core_access;
//! Increment iterator
void increment();
//! Check for equality
bool equal(CartesianProductIterator<T> const& other) const;
//! Dereference iterator
std::vector<Content> const& dereference() const;
//! The part we are iterating over
OuterContainer const& structure_;
//! The position in the Cartesian product
/*!
* For each element of structure_, give the position in it.
* The empty vector represents the end position.
* Note that this vector has a size equal to structure->size(), or is empty.
*/
std::vector<typename Container::const_iterator> position_;
//! The position just indexed by an integer
std::size_t absolutePosition_ = 0;
//! The begin iterators, saved for convenience and performance
std::vector<typename Container::const_iterator> cbegins_;
//! The end iterators, saved for convenience and performance
std::vector<typename Container::const_iterator> cends_;
//! Used for returning references
/*!
* We initialize with one empty element, so that we only need to add more elements in increment().
*/
mutable std::vector<std::vector<Content>> result_{std::vector<Content>()};
//! The size of the instance of OuterContainer
std::size_t size_ = 0;
};
template<typename T>
CartesianProductIterator<T>::CartesianProductIterator(OuterContainer const& structure, std::size_t pos) : structure_(structure)
{
for(auto & entry: structure_) {
cbegins_.push_back(entry.cbegin());
cends_.push_back(entry.cend());
++size_;
}
if(pos == std::numeric_limits<std::size_t>::max() || size_ == 0) {
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
// Initialize with all cbegin() position
position_.reserve(size_);
for(std::size_t i = 0; i != size_; ++i) {
position_.push_back(cbegins_[i]);
if(cbegins_[i] == cends_[i]) {
// Empty member, so Cartesian product is empty
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
}
// Increment to wanted position
for(std::size_t i = 0; i < pos; ++i) {
increment();
}
}
template<typename T>
void CartesianProductIterator<T>::increment()
{
if(absolutePosition_ == std::numeric_limits<std::size_t>::max()) {
return;
}
std::size_t pos = size_ - 1;
// Descend as far as necessary
while(++(position_[pos]) == cends_[pos] && pos != 0) {
--pos;
}
if(position_[pos] == cends_[pos]) {
assert(pos == 0);
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
// Set all to begin behind pos
for(++pos; pos != size_; ++pos) {
position_[pos] = cbegins_[pos];
}
++absolutePosition_;
result_.emplace_back();
}
template<typename T>
std::vector<typename T::value_type::value_type> const& CartesianProductIterator<T>::dereference() const
{
if(absolutePosition_ == std::numeric_limits<std::size_t>::max()) {
throw new std::out_of_range("Out of bound dereference in CartesianProductIterator\n");
}
auto & result = result_[absolutePosition_];
if(result.empty()) {
result.reserve(size_);
for(auto & iterator: position_) {
result.push_back(*iterator);
}
}
return result;
}
template<typename T>
bool CartesianProductIterator<T>::equal(CartesianProductIterator<T> const& other) const
{
return absolutePosition_ == other.absolutePosition_ && structure_ == other.structure_;
}
//! Class that turns a forward iterable container of forward iterable containers into a forward iterable container which iterates over the Cartesian product of the forward iterable containers
template<typename T>
class CartesianProduct
{
public:
//! Constructor from type T
explicit CartesianProduct(T const& t) : t_(t) {}
//! Iterator to beginning of Cartesian product
CartesianProductIterator<T> begin() const { return CartesianProductIterator<T>(t_, 0); }
//! Iterator behind the last element of the Cartesian product
CartesianProductIterator<T> end() const { return CartesianProductIterator<T>(t_, std::numeric_limits<std::size_t>::max()); }
private:
T const& t_;
};
If someone has comments how to make it faster or better, I'd highly appreciate them.
I was just forced to implement this for a project I was working on and I came up with the code below. It can be stuck in a header and it's use is very simple but it returns all of the combinations you can get from a vector of vectors. The array that it returns only holds integers. This was a conscious decision because I just wanted the indices. In this way, I could index into each of the vector's vector and then perform the calculations I/anyone would need... best to avoid letting CartesianProduct hold "stuff" itself, it is a mathematical concept based around counting not a data structure. I'm fairly new to c++ but this was tested in a decryption algorithm pretty thoroughly. There is some light recursion but overall this is a simple implementation of a simple counting concept.
// Use of the CartesianProduct class is as follows. Give it the number
// of rows and the sizes of each of the rows. It will output all of the
// permutations of these numbers in their respective rows.
// 1. call cp.permutation() // need to check all 0s.
// 2. while cp.HasNext() // it knows the exit condition form its inputs.
// 3. cp.Increment() // Make the next permutation
// 4. cp.permutation() // get the next permutation
class CartesianProduct{
public:
CartesianProduct(int num_rows, vector<int> sizes_of_rows){
permutation_ = new int[num_rows];
num_rows_ = num_rows;
ZeroOutPermutation();
sizes_of_rows_ = sizes_of_rows;
num_max_permutations_ = 1;
for (int i = 0; i < num_rows; ++i){
num_max_permutations_ *= sizes_of_rows_[i];
}
}
~CartesianProduct(){
delete permutation_;
}
bool HasNext(){
if(num_permutations_processed_ != num_max_permutations_) {
return true;
} else {
return false;
}
}
void Increment(){
int row_to_increment = 0;
++num_permutations_processed_;
IncrementAndTest(row_to_increment);
}
int* permutation(){
return permutation_;
}
int num_permutations_processed(){
return num_permutations_processed_;
}
void PrintPermutation(){
cout << "( ";
for (int i = 0; i < num_rows_; ++i){
cout << permutation_[i] << ", ";
}
cout << " )" << endl;
}
private:
int num_permutations_processed_;
int *permutation_;
int num_rows_;
int num_max_permutations_;
vector<int> sizes_of_rows_;
// Because CartesianProduct is called first initially with it's values
// of 0 and because those values are valid and important output
// of the CartesianProduct we increment the number of permutations
// processed here when we populate the permutation_ array with 0s.
void ZeroOutPermutation(){
for (int i = 0; i < num_rows_; ++i){
permutation_[i] = 0;
}
num_permutations_processed_ = 1;
}
void IncrementAndTest(int row_to_increment){
permutation_[row_to_increment] += 1;
int max_index_of_row = sizes_of_rows_[row_to_increment] - 1;
if (permutation_[row_to_increment] > max_index_of_row){
permutation_[row_to_increment] = 0;
IncrementAndTest(row_to_increment + 1);
}
}
};
#include <iostream>
#include <vector>
void cartesian (std::vector<std::vector<int>> const& items) {
auto n = items.size();
auto next = [&](std::vector<int> & x) {
for ( int i = 0; i < n; ++ i )
if ( ++x[i] == items[i].size() ) x[i] = 0;
else return true;
return false;
};
auto print = [&](std::vector<int> const& x) {
for ( int i = 0; i < n; ++ i )
std::cout << items[i][x[i]] << ",";
std::cout << "\b \n";
};
std::vector<int> x(n);
do print(x); while (next(x)); // Shazam!
}
int main () {
std::vector<std::vector<int>>
items { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
cartesian(items);
return 0;
}
The idea behind this is as follows.
Let n := items.size().
Let m_i := items[i].size(), for all i in {0,1,...,n-1}.
Let M := {0,1,...,m_0-1} x {0,1,...,m_1-1} x ... x {0,1,...,m_{n-1}-1}.
We first solve the simpler problem of iterating through M. This is accomplished by the next lambda. The algorithm is simply the "carrying" routine grade schoolers use to add 1, albeit with a mixed radix number system.
We use this to solve the more general problem by transforming a tuple x in M to one of the desired tuples via the formula items[i][x[i]] for all i in {0,1,...,n-1}. We perform this transformation in the print lambda.
We then perform the iteration with do print(x); while (next(x));.
Now some comments on complexity, under the assumption that m_i > 1 for all i:
This algorithm requires O(n) space. Note that explicit construction of the Cartesian product takes O(m_0 m_1 m_2 ... m_{n-1}) >= O(2^n) space. So this is exponentially better on space than any algorithm which requires all tuples to be stored simultaneously in memory.
The next function takes amortized O(1) time (by a geometric series argument).
The print function takes O(n) time.
Hence, altogether, the algorithm has time complexity O(n|M|) and space complexity O(n) (not counting the cost of storing items).
An interesting thing to note is that if print is replaced with a function which inspects on average only O(1) coordinates per tuple rather than all of them, then time complexity falls to O(|M|), that is, it becomes linear time with respect to the size of the Cartesian product. In other words, avoiding the copy of the tuple each iterate can be meaningful in some situations.
This version supports no iterators or ranges, but it is a simple direct implementation that uses the multiplication operator to represent the Cartesian product, and a lambda to perform the action.
The interface is designed with the particular functionality I needed. I needed the flexibility to choose vectors over which to apply the Cartesian product in a way that did not obscure the code.
int main()
{
vector< vector<long> > v{ { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
(Cartesian<long>(v[0]) * v[1] * v[2]).ForEach(
[](long p_Depth, long *p_LongList)
{
std::cout << p_LongList[0] << " " << p_LongList[1] << " " << p_LongList[2] << std::endl;
}
);
}
The implementation uses recursion up the class structure to implement the embedded for loops over each vector. The algorithm works directly on the input vectors, requiring no large temporary arrays. It is simple to understand and debug.
The use of std::function p_Action instead of void p_Action(long p_Depth, T *p_ParamList) for the lambda parameter would allow me to capture local variables, if I wanted to. In the above call, I don't.
But you knew that, didn't you. "function" is a template class which takes the type parameter of a function and makes it callable.
#include <vector>
#include <iostream>
#include <functional>
#include <string>
using namespace std;
template <class T>
class Cartesian
{
private:
vector<T> &m_Vector;
Cartesian<T> *m_Cartesian;
public:
Cartesian(vector<T> &p_Vector, Cartesian<T> *p_Cartesian=NULL)
: m_Vector(p_Vector), m_Cartesian(p_Cartesian)
{};
virtual ~Cartesian() {};
Cartesian<T> *Clone()
{
return new Cartesian<T>(m_Vector, m_Cartesian ? m_Cartesian->Clone() : NULL);
};
Cartesian<T> &operator *=(vector<T> &p_Vector)
{
if (m_Cartesian)
(*m_Cartesian) *= p_Vector;
else
m_Cartesian = new Cartesian(p_Vector);
return *this;
};
Cartesian<T> operator *(vector<T> &p_Vector)
{
return (*Clone()) *= p_Vector;
};
long Depth()
{
return m_Cartesian ? 1 + m_Cartesian->Depth() : 1;
};
void ForEach(function<void (long p_Depth, T *p_ParamList)> p_Action)
{
Loop(0, new T[Depth()], p_Action);
};
private:
void Loop(long p_Depth, T *p_ParamList, function<void (long p_Depth, T *p_ParamList)> p_Action)
{
for (T &element : m_Vector)
{
p_ParamList[p_Depth] = element;
if (m_Cartesian)
m_Cartesian->Loop(p_Depth + 1, p_ParamList, p_Action);
else
p_Action(Depth(), p_ParamList);
}
};
};

std::iota is very limited

Coming from a Python world, I find the function std::iota very limited. Why is the interface restricted to not take any UnaryFunction ?
For instance I can convert
>>> x = range(0, 10)
into
std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0);
But how would one do:
>>> x = range(0,20,2)
or even
>>> x = range(10,0,-1)
I know this is trivial to write one such function or use Boost, but I figured that C++ committee must have picked this design with care. So clearly I am missing something from C++11.
how about std::generate?
int n = -2;
std::generate(x.begin(), x.end(), [&n]{ return n+=2; });
int n = 10;
std::generate(x.begin(), x.end(), [&n]{ return n--;});
But how would one do:
x = range(0,20,2)
Alternatively to std::generate() (see other answer), you can provide your own unary function to std::iota(), it just have to be called operator++():
#include <iostream>
#include <functional>
#include <numeric>
#include <vector>
template<class T>
struct IotaWrapper
{
typedef T type;
typedef std::function<type(const type&)> IncrFunction;
type value;
IncrFunction incrFunction;
IotaWrapper() = delete;
IotaWrapper(const type& n, const IncrFunction& incrFunction) : value(n), incrFunction(incrFunction) {};
operator type() { return value; }
IotaWrapper& operator++() { value = incrFunction(value); return *this; }
};
int main()
{
IotaWrapper<int> n(0, [](const int& n){ return n+2; });
std::vector<int> v(10);
std::iota(v.begin(), v.end(), n);
for (auto i : v)
std::cout << i << ' ';
std::cout << std::endl;
}
Output: 0 2 4 6 8 10 12 14 16 18
Demo
Here is an idea of how one could implement Range():
struct Range
{
template<class Value, class Incr>
std::vector<Value> operator()(const Value& first, const Value& last, const Incr& increment)
{
IotaWrapper<Value> iota(first, [=](const int& n){ return n+increment; });
std::vector<Value> result((last - first) / increment);
std::iota(result.begin(), result.end(), iota);
return result;
}
};
Demo
With C++20 ranges, you can write it like this:
static auto stepped_iota(int start, int step) {
return std::ranges::views::iota(0) |
std::ranges::views::transform([=](int x) { return x * step + start; });
}
void f() {
for (int x : stepped_iota(0, 2)) { ... }
}
https://godbolt.org/z/3G49rs
Or, if you want the range to be finite:
static auto stepped_iota(int start, int end, int step) {
return std::ranges::views::iota(0, (end - start + step - 1) / step) |
std::ranges::views::transform([=](int x) { return x * step + start; });
}

Cartesian product from a vector in C++11? [duplicate]

I've a vector of vectors say vector<vector<int> > items of different sizes like as follows
1,2,3
4,5
6,7,8
I want to create combinations in terms of Cartesian product of these vectors like
1,4,6
1,4,7
1,4,8
and so on till
3,5,8
How can I do that ? I've looked up several links and I've also listed them at the end of this post but I'm not able to interpret that as I'm not that familiar with the language. Could some body help me with this.
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
vector<vector<int> > items;
int k = 0;
for ( int i = 0; i < 5; i++ ) {
items.push_back ( vector<int>() );
for ( int j = 0; j < 5; j++ )
items[i].push_back ( k++ );
}
cartesian ( items ); // I want some function here to do this.
}
This program has equal length vectors and I put this so that it will be easier to understand my data structure. It will be very helpful even if somebody uses others answers from other links and integrate with this to get the result. Thank you very much
Couple of links I looked at
one
Two
Program from : program
First, I'll show you a recursive version.
// Cartesion product of vector of vectors
#include <vector>
#include <iostream>
#include <iterator>
// Types to hold vector-of-ints (Vi) and vector-of-vector-of-ints (Vvi)
typedef std::vector<int> Vi;
typedef std::vector<Vi> Vvi;
// Just for the sample -- populate the intput data set
Vvi build_input() {
Vvi vvi;
for(int i = 0; i < 3; i++) {
Vi vi;
for(int j = 0; j < 3; j++) {
vi.push_back(i*10+j);
}
vvi.push_back(vi);
}
return vvi;
}
// just for the sample -- print the data sets
std::ostream&
operator<<(std::ostream& os, const Vi& vi)
{
os << "(";
std::copy(vi.begin(), vi.end(), std::ostream_iterator<int>(os, ", "));
os << ")";
return os;
}
std::ostream&
operator<<(std::ostream& os, const Vvi& vvi)
{
os << "(\n";
for(Vvi::const_iterator it = vvi.begin();
it != vvi.end();
it++) {
os << " " << *it << "\n";
}
os << ")";
return os;
}
// recursive algorithm to to produce cart. prod.
// At any given moment, "me" points to some Vi in the middle of the
// input data set.
// for int i in *me:
// add i to current result
// recurse on next "me"
//
void cart_product(
Vvi& rvvi, // final result
Vi& rvi, // current result
Vvi::const_iterator me, // current input
Vvi::const_iterator end) // final input
{
if(me == end) {
// terminal condition of the recursion. We no longer have
// any input vectors to manipulate. Add the current result (rvi)
// to the total set of results (rvvvi).
rvvi.push_back(rvi);
return;
}
// need an easy name for my vector-of-ints
const Vi& mevi = *me;
for(Vi::const_iterator it = mevi.begin();
it != mevi.end();
it++) {
// final rvi will look like "a, b, c, ME, d, e, f"
// At the moment, rvi already has "a, b, c"
rvi.push_back(*it); // add ME
cart_product(rvvi, rvi, me+1, end); add "d, e, f"
rvi.pop_back(); // clean ME off for next round
}
}
// sample only, to drive the cart_product routine.
int main() {
Vvi input(build_input());
std::cout << input << "\n";
Vvi output;
Vi outputTemp;
cart_product(output, outputTemp, input.begin(), input.end());
std::cout << output << "\n";
}
Now, I'll show you the recursive iterative version that I shamelessly stole from #John :
The rest of the program is pretty much the same, only showing the cart_product function.
// Seems like you'd want a vector of iterators
// which iterate over your individual vector<int>s.
struct Digits {
Vi::const_iterator begin;
Vi::const_iterator end;
Vi::const_iterator me;
};
typedef std::vector<Digits> Vd;
void cart_product(
Vvi& out, // final result
Vvi& in) // final result
{
Vd vd;
// Start all of the iterators at the beginning.
for(Vvi::const_iterator it = in.begin();
it != in.end();
++it) {
Digits d = {(*it).begin(), (*it).end(), (*it).begin()};
vd.push_back(d);
}
while(1) {
// Construct your first product vector by pulling
// out the element of each vector via the iterator.
Vi result;
for(Vd::const_iterator it = vd.begin();
it != vd.end();
it++) {
result.push_back(*(it->me));
}
out.push_back(result);
// Increment the rightmost one, and repeat.
// When you reach the end, reset that one to the beginning and
// increment the next-to-last one. You can get the "next-to-last"
// iterator by pulling it out of the neighboring element in your
// vector of iterators.
for(Vd::iterator it = vd.begin(); ; ) {
// okay, I started at the left instead. sue me
++(it->me);
if(it->me == it->end) {
if(it+1 == vd.end()) {
// I'm the last digit, and I'm about to roll
return;
} else {
// cascade
it->me = it->begin;
++it;
}
} else {
// normal
break;
}
}
}
}
Here is a solution in C++11.
The indexing of the variable-sized arrays can be done eloquently with modular arithmetic.
The total number of lines in the output is the product of the sizes of the input vectors. That is:
N = v[0].size() * v[1].size() * v[2].size()
Therefore the main loop has n as the iteration variable, from 0 to N-1. In principle, each value of n encodes enough information to extract each of the indices of v for that iteration. This is done in a subloop using repeated modular arithmetic:
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void cartesian( vector<vector<int> >& v ) {
auto product = []( long long a, vector<int>& b ) { return a*b.size(); };
const long long N = accumulate( v.begin(), v.end(), 1LL, product );
vector<int> u(v.size());
for( long long n=0 ; n<N ; ++n ) {
lldiv_t q { n, 0 };
for( long long i=v.size()-1 ; 0<=i ; --i ) {
q = div( q.quot, v[i].size() );
u[i] = v[i][q.rem];
}
// Do what you want here with u.
for( int x : u ) cout << x << ' ';
cout << '\n';
}
}
int main() {
vector<vector<int> > v { { 1, 2, 3 },
{ 4, 5 },
{ 6, 7, 8 } };
cartesian(v);
return 0;
}
Output:
1 4 6
1 4 7
1 4 8
...
3 5 8
Shorter code:
vector<vector<int>> cart_product (const vector<vector<int>>& v) {
vector<vector<int>> s = {{}};
for (const auto& u : v) {
vector<vector<int>> r;
for (const auto& x : s) {
for (const auto y : u) {
r.push_back(x);
r.back().push_back(y);
}
}
s = move(r);
}
return s;
}
Seems like you'd want a vector of iterators which iterate over your individual vector<int>s.
Start all of the iterators at the beginning. Construct your first product vector by pulling out the element of each vector via the iterator.
Increment the rightmost one, and repeat.
When you reach the end, reset that one to the beginning and increment the next-to-last one. You can get the "next-to-last" iterator by pulling it out of the neighboring element in your vector of iterators.
Continue cycling through until both the last and next-to-last iterators are at the end. Then, reset them both, increment the third-from-last iterator. In general, this can be cascaded.
It's like an odometer, but with each different digit being in a different base.
Here's my solution. Also iterative, but a little shorter than the above...
void xp(const vector<vector<int>*>& vecs, vector<vector<int>*> *result) {
vector<vector<int>*>* rslts;
for (int ii = 0; ii < vecs.size(); ++ii) {
const vector<int>& vec = *vecs[ii];
if (ii == 0) {
// vecs=[[1,2],...] ==> rslts=[[1],[2]]
rslts = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) {
vector<int>* v = new vector<int>;
v->push_back(vec[jj]);
rslts->push_back(v);
}
} else {
// vecs=[[1,2],[3,4],...] ==> rslts=[[1,3],[1,4],[2,3],[2,4]]
vector<vector<int>*>* tmp = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) { // vec[jj]=3 (first iter jj=0)
for (vector<vector<int>*>::const_iterator it = rslts->begin();
it != rslts->end(); ++it) {
vector<int>* v = new vector<int>(**it); // v=[1]
v->push_back(vec[jj]); // v=[1,3]
tmp->push_back(v); // tmp=[[1,3]]
}
}
for (int kk = 0; kk < rslts->size(); ++kk) {
delete (*rslts)[kk];
}
delete rslts;
rslts = tmp;
}
}
result->insert(result->end(), rslts->begin(), rslts->end());
delete rslts;
}
I derived it with some pain from a haskell version I wrote:
xp :: [[a]] -> [[a]]
xp [] = []
xp [l] = map (:[]) l
xp (h:t) = foldr (\x acc -> foldr (\l acc -> (x:l):acc) acc (xp t)) [] h
Since I needed the same functionality, I implemented an iterator which computes the Cartesian product on the fly, as needed, and iterates over it.
It can be used as follows.
#include <forward_list>
#include <iostream>
#include <vector>
#include "cartesian.hpp"
int main()
{
// Works with a vector of vectors
std::vector<std::vector<int>> test{{1,2,3}, {4,5,6}, {8,9}};
CartesianProduct<decltype(test)> cp(test);
for(auto const& val: cp) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
// Also works with something much less, like a forward_list of forward_lists
std::forward_list<std::forward_list<std::string>> foo{{"boo", "far", "zab"}, {"zoo", "moo"}, {"yohoo", "bohoo", "whoot", "noo"}};
CartesianProduct<decltype(foo)> bar(foo);
for(auto const& val: bar) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
}
The file cartesian.hpp looks like this.
#include <cassert>
#include <limits>
#include <stdexcept>
#include <vector>
#include <boost/iterator/iterator_facade.hpp>
//! Class iterating over the Cartesian product of a forward iterable container of forward iterable containers
template<typename T>
class CartesianProductIterator : public boost::iterator_facade<CartesianProductIterator<T>, std::vector<typename T::value_type::value_type> const, boost::forward_traversal_tag>
{
public:
//! Delete default constructor
CartesianProductIterator() = delete;
//! Constructor setting the underlying iterator and position
/*!
* \param[in] structure The underlying structure
* \param[in] pos The position the iterator should be initialized to. std::numeric_limits<std::size_t>::max()stands for the end, the position after the last element.
*/
explicit CartesianProductIterator(T const& structure, std::size_t pos);
private:
//! Give types more descriptive names
// \{
typedef T OuterContainer;
typedef typename T::value_type Container;
typedef typename T::value_type::value_type Content;
// \}
//! Grant access to boost::iterator_facade
friend class boost::iterator_core_access;
//! Increment iterator
void increment();
//! Check for equality
bool equal(CartesianProductIterator<T> const& other) const;
//! Dereference iterator
std::vector<Content> const& dereference() const;
//! The part we are iterating over
OuterContainer const& structure_;
//! The position in the Cartesian product
/*!
* For each element of structure_, give the position in it.
* The empty vector represents the end position.
* Note that this vector has a size equal to structure->size(), or is empty.
*/
std::vector<typename Container::const_iterator> position_;
//! The position just indexed by an integer
std::size_t absolutePosition_ = 0;
//! The begin iterators, saved for convenience and performance
std::vector<typename Container::const_iterator> cbegins_;
//! The end iterators, saved for convenience and performance
std::vector<typename Container::const_iterator> cends_;
//! Used for returning references
/*!
* We initialize with one empty element, so that we only need to add more elements in increment().
*/
mutable std::vector<std::vector<Content>> result_{std::vector<Content>()};
//! The size of the instance of OuterContainer
std::size_t size_ = 0;
};
template<typename T>
CartesianProductIterator<T>::CartesianProductIterator(OuterContainer const& structure, std::size_t pos) : structure_(structure)
{
for(auto & entry: structure_) {
cbegins_.push_back(entry.cbegin());
cends_.push_back(entry.cend());
++size_;
}
if(pos == std::numeric_limits<std::size_t>::max() || size_ == 0) {
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
// Initialize with all cbegin() position
position_.reserve(size_);
for(std::size_t i = 0; i != size_; ++i) {
position_.push_back(cbegins_[i]);
if(cbegins_[i] == cends_[i]) {
// Empty member, so Cartesian product is empty
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
}
// Increment to wanted position
for(std::size_t i = 0; i < pos; ++i) {
increment();
}
}
template<typename T>
void CartesianProductIterator<T>::increment()
{
if(absolutePosition_ == std::numeric_limits<std::size_t>::max()) {
return;
}
std::size_t pos = size_ - 1;
// Descend as far as necessary
while(++(position_[pos]) == cends_[pos] && pos != 0) {
--pos;
}
if(position_[pos] == cends_[pos]) {
assert(pos == 0);
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
// Set all to begin behind pos
for(++pos; pos != size_; ++pos) {
position_[pos] = cbegins_[pos];
}
++absolutePosition_;
result_.emplace_back();
}
template<typename T>
std::vector<typename T::value_type::value_type> const& CartesianProductIterator<T>::dereference() const
{
if(absolutePosition_ == std::numeric_limits<std::size_t>::max()) {
throw new std::out_of_range("Out of bound dereference in CartesianProductIterator\n");
}
auto & result = result_[absolutePosition_];
if(result.empty()) {
result.reserve(size_);
for(auto & iterator: position_) {
result.push_back(*iterator);
}
}
return result;
}
template<typename T>
bool CartesianProductIterator<T>::equal(CartesianProductIterator<T> const& other) const
{
return absolutePosition_ == other.absolutePosition_ && structure_ == other.structure_;
}
//! Class that turns a forward iterable container of forward iterable containers into a forward iterable container which iterates over the Cartesian product of the forward iterable containers
template<typename T>
class CartesianProduct
{
public:
//! Constructor from type T
explicit CartesianProduct(T const& t) : t_(t) {}
//! Iterator to beginning of Cartesian product
CartesianProductIterator<T> begin() const { return CartesianProductIterator<T>(t_, 0); }
//! Iterator behind the last element of the Cartesian product
CartesianProductIterator<T> end() const { return CartesianProductIterator<T>(t_, std::numeric_limits<std::size_t>::max()); }
private:
T const& t_;
};
If someone has comments how to make it faster or better, I'd highly appreciate them.
I was just forced to implement this for a project I was working on and I came up with the code below. It can be stuck in a header and it's use is very simple but it returns all of the combinations you can get from a vector of vectors. The array that it returns only holds integers. This was a conscious decision because I just wanted the indices. In this way, I could index into each of the vector's vector and then perform the calculations I/anyone would need... best to avoid letting CartesianProduct hold "stuff" itself, it is a mathematical concept based around counting not a data structure. I'm fairly new to c++ but this was tested in a decryption algorithm pretty thoroughly. There is some light recursion but overall this is a simple implementation of a simple counting concept.
// Use of the CartesianProduct class is as follows. Give it the number
// of rows and the sizes of each of the rows. It will output all of the
// permutations of these numbers in their respective rows.
// 1. call cp.permutation() // need to check all 0s.
// 2. while cp.HasNext() // it knows the exit condition form its inputs.
// 3. cp.Increment() // Make the next permutation
// 4. cp.permutation() // get the next permutation
class CartesianProduct{
public:
CartesianProduct(int num_rows, vector<int> sizes_of_rows){
permutation_ = new int[num_rows];
num_rows_ = num_rows;
ZeroOutPermutation();
sizes_of_rows_ = sizes_of_rows;
num_max_permutations_ = 1;
for (int i = 0; i < num_rows; ++i){
num_max_permutations_ *= sizes_of_rows_[i];
}
}
~CartesianProduct(){
delete permutation_;
}
bool HasNext(){
if(num_permutations_processed_ != num_max_permutations_) {
return true;
} else {
return false;
}
}
void Increment(){
int row_to_increment = 0;
++num_permutations_processed_;
IncrementAndTest(row_to_increment);
}
int* permutation(){
return permutation_;
}
int num_permutations_processed(){
return num_permutations_processed_;
}
void PrintPermutation(){
cout << "( ";
for (int i = 0; i < num_rows_; ++i){
cout << permutation_[i] << ", ";
}
cout << " )" << endl;
}
private:
int num_permutations_processed_;
int *permutation_;
int num_rows_;
int num_max_permutations_;
vector<int> sizes_of_rows_;
// Because CartesianProduct is called first initially with it's values
// of 0 and because those values are valid and important output
// of the CartesianProduct we increment the number of permutations
// processed here when we populate the permutation_ array with 0s.
void ZeroOutPermutation(){
for (int i = 0; i < num_rows_; ++i){
permutation_[i] = 0;
}
num_permutations_processed_ = 1;
}
void IncrementAndTest(int row_to_increment){
permutation_[row_to_increment] += 1;
int max_index_of_row = sizes_of_rows_[row_to_increment] - 1;
if (permutation_[row_to_increment] > max_index_of_row){
permutation_[row_to_increment] = 0;
IncrementAndTest(row_to_increment + 1);
}
}
};
#include <iostream>
#include <vector>
void cartesian (std::vector<std::vector<int>> const& items) {
auto n = items.size();
auto next = [&](std::vector<int> & x) {
for ( int i = 0; i < n; ++ i )
if ( ++x[i] == items[i].size() ) x[i] = 0;
else return true;
return false;
};
auto print = [&](std::vector<int> const& x) {
for ( int i = 0; i < n; ++ i )
std::cout << items[i][x[i]] << ",";
std::cout << "\b \n";
};
std::vector<int> x(n);
do print(x); while (next(x)); // Shazam!
}
int main () {
std::vector<std::vector<int>>
items { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
cartesian(items);
return 0;
}
The idea behind this is as follows.
Let n := items.size().
Let m_i := items[i].size(), for all i in {0,1,...,n-1}.
Let M := {0,1,...,m_0-1} x {0,1,...,m_1-1} x ... x {0,1,...,m_{n-1}-1}.
We first solve the simpler problem of iterating through M. This is accomplished by the next lambda. The algorithm is simply the "carrying" routine grade schoolers use to add 1, albeit with a mixed radix number system.
We use this to solve the more general problem by transforming a tuple x in M to one of the desired tuples via the formula items[i][x[i]] for all i in {0,1,...,n-1}. We perform this transformation in the print lambda.
We then perform the iteration with do print(x); while (next(x));.
Now some comments on complexity, under the assumption that m_i > 1 for all i:
This algorithm requires O(n) space. Note that explicit construction of the Cartesian product takes O(m_0 m_1 m_2 ... m_{n-1}) >= O(2^n) space. So this is exponentially better on space than any algorithm which requires all tuples to be stored simultaneously in memory.
The next function takes amortized O(1) time (by a geometric series argument).
The print function takes O(n) time.
Hence, altogether, the algorithm has time complexity O(n|M|) and space complexity O(n) (not counting the cost of storing items).
An interesting thing to note is that if print is replaced with a function which inspects on average only O(1) coordinates per tuple rather than all of them, then time complexity falls to O(|M|), that is, it becomes linear time with respect to the size of the Cartesian product. In other words, avoiding the copy of the tuple each iterate can be meaningful in some situations.
This version supports no iterators or ranges, but it is a simple direct implementation that uses the multiplication operator to represent the Cartesian product, and a lambda to perform the action.
The interface is designed with the particular functionality I needed. I needed the flexibility to choose vectors over which to apply the Cartesian product in a way that did not obscure the code.
int main()
{
vector< vector<long> > v{ { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
(Cartesian<long>(v[0]) * v[1] * v[2]).ForEach(
[](long p_Depth, long *p_LongList)
{
std::cout << p_LongList[0] << " " << p_LongList[1] << " " << p_LongList[2] << std::endl;
}
);
}
The implementation uses recursion up the class structure to implement the embedded for loops over each vector. The algorithm works directly on the input vectors, requiring no large temporary arrays. It is simple to understand and debug.
The use of std::function p_Action instead of void p_Action(long p_Depth, T *p_ParamList) for the lambda parameter would allow me to capture local variables, if I wanted to. In the above call, I don't.
But you knew that, didn't you. "function" is a template class which takes the type parameter of a function and makes it callable.
#include <vector>
#include <iostream>
#include <functional>
#include <string>
using namespace std;
template <class T>
class Cartesian
{
private:
vector<T> &m_Vector;
Cartesian<T> *m_Cartesian;
public:
Cartesian(vector<T> &p_Vector, Cartesian<T> *p_Cartesian=NULL)
: m_Vector(p_Vector), m_Cartesian(p_Cartesian)
{};
virtual ~Cartesian() {};
Cartesian<T> *Clone()
{
return new Cartesian<T>(m_Vector, m_Cartesian ? m_Cartesian->Clone() : NULL);
};
Cartesian<T> &operator *=(vector<T> &p_Vector)
{
if (m_Cartesian)
(*m_Cartesian) *= p_Vector;
else
m_Cartesian = new Cartesian(p_Vector);
return *this;
};
Cartesian<T> operator *(vector<T> &p_Vector)
{
return (*Clone()) *= p_Vector;
};
long Depth()
{
return m_Cartesian ? 1 + m_Cartesian->Depth() : 1;
};
void ForEach(function<void (long p_Depth, T *p_ParamList)> p_Action)
{
Loop(0, new T[Depth()], p_Action);
};
private:
void Loop(long p_Depth, T *p_ParamList, function<void (long p_Depth, T *p_ParamList)> p_Action)
{
for (T &element : m_Vector)
{
p_ParamList[p_Depth] = element;
if (m_Cartesian)
m_Cartesian->Loop(p_Depth + 1, p_ParamList, p_Action);
else
p_Action(Depth(), p_ParamList);
}
};
};

How can I create cartesian product of vector of vectors?

I've a vector of vectors say vector<vector<int> > items of different sizes like as follows
1,2,3
4,5
6,7,8
I want to create combinations in terms of Cartesian product of these vectors like
1,4,6
1,4,7
1,4,8
and so on till
3,5,8
How can I do that ? I've looked up several links and I've also listed them at the end of this post but I'm not able to interpret that as I'm not that familiar with the language. Could some body help me with this.
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
vector<vector<int> > items;
int k = 0;
for ( int i = 0; i < 5; i++ ) {
items.push_back ( vector<int>() );
for ( int j = 0; j < 5; j++ )
items[i].push_back ( k++ );
}
cartesian ( items ); // I want some function here to do this.
}
This program has equal length vectors and I put this so that it will be easier to understand my data structure. It will be very helpful even if somebody uses others answers from other links and integrate with this to get the result. Thank you very much
Couple of links I looked at
one
Two
Program from : program
First, I'll show you a recursive version.
// Cartesion product of vector of vectors
#include <vector>
#include <iostream>
#include <iterator>
// Types to hold vector-of-ints (Vi) and vector-of-vector-of-ints (Vvi)
typedef std::vector<int> Vi;
typedef std::vector<Vi> Vvi;
// Just for the sample -- populate the intput data set
Vvi build_input() {
Vvi vvi;
for(int i = 0; i < 3; i++) {
Vi vi;
for(int j = 0; j < 3; j++) {
vi.push_back(i*10+j);
}
vvi.push_back(vi);
}
return vvi;
}
// just for the sample -- print the data sets
std::ostream&
operator<<(std::ostream& os, const Vi& vi)
{
os << "(";
std::copy(vi.begin(), vi.end(), std::ostream_iterator<int>(os, ", "));
os << ")";
return os;
}
std::ostream&
operator<<(std::ostream& os, const Vvi& vvi)
{
os << "(\n";
for(Vvi::const_iterator it = vvi.begin();
it != vvi.end();
it++) {
os << " " << *it << "\n";
}
os << ")";
return os;
}
// recursive algorithm to to produce cart. prod.
// At any given moment, "me" points to some Vi in the middle of the
// input data set.
// for int i in *me:
// add i to current result
// recurse on next "me"
//
void cart_product(
Vvi& rvvi, // final result
Vi& rvi, // current result
Vvi::const_iterator me, // current input
Vvi::const_iterator end) // final input
{
if(me == end) {
// terminal condition of the recursion. We no longer have
// any input vectors to manipulate. Add the current result (rvi)
// to the total set of results (rvvvi).
rvvi.push_back(rvi);
return;
}
// need an easy name for my vector-of-ints
const Vi& mevi = *me;
for(Vi::const_iterator it = mevi.begin();
it != mevi.end();
it++) {
// final rvi will look like "a, b, c, ME, d, e, f"
// At the moment, rvi already has "a, b, c"
rvi.push_back(*it); // add ME
cart_product(rvvi, rvi, me+1, end); add "d, e, f"
rvi.pop_back(); // clean ME off for next round
}
}
// sample only, to drive the cart_product routine.
int main() {
Vvi input(build_input());
std::cout << input << "\n";
Vvi output;
Vi outputTemp;
cart_product(output, outputTemp, input.begin(), input.end());
std::cout << output << "\n";
}
Now, I'll show you the recursive iterative version that I shamelessly stole from #John :
The rest of the program is pretty much the same, only showing the cart_product function.
// Seems like you'd want a vector of iterators
// which iterate over your individual vector<int>s.
struct Digits {
Vi::const_iterator begin;
Vi::const_iterator end;
Vi::const_iterator me;
};
typedef std::vector<Digits> Vd;
void cart_product(
Vvi& out, // final result
Vvi& in) // final result
{
Vd vd;
// Start all of the iterators at the beginning.
for(Vvi::const_iterator it = in.begin();
it != in.end();
++it) {
Digits d = {(*it).begin(), (*it).end(), (*it).begin()};
vd.push_back(d);
}
while(1) {
// Construct your first product vector by pulling
// out the element of each vector via the iterator.
Vi result;
for(Vd::const_iterator it = vd.begin();
it != vd.end();
it++) {
result.push_back(*(it->me));
}
out.push_back(result);
// Increment the rightmost one, and repeat.
// When you reach the end, reset that one to the beginning and
// increment the next-to-last one. You can get the "next-to-last"
// iterator by pulling it out of the neighboring element in your
// vector of iterators.
for(Vd::iterator it = vd.begin(); ; ) {
// okay, I started at the left instead. sue me
++(it->me);
if(it->me == it->end) {
if(it+1 == vd.end()) {
// I'm the last digit, and I'm about to roll
return;
} else {
// cascade
it->me = it->begin;
++it;
}
} else {
// normal
break;
}
}
}
}
Here is a solution in C++11.
The indexing of the variable-sized arrays can be done eloquently with modular arithmetic.
The total number of lines in the output is the product of the sizes of the input vectors. That is:
N = v[0].size() * v[1].size() * v[2].size()
Therefore the main loop has n as the iteration variable, from 0 to N-1. In principle, each value of n encodes enough information to extract each of the indices of v for that iteration. This is done in a subloop using repeated modular arithmetic:
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void cartesian( vector<vector<int> >& v ) {
auto product = []( long long a, vector<int>& b ) { return a*b.size(); };
const long long N = accumulate( v.begin(), v.end(), 1LL, product );
vector<int> u(v.size());
for( long long n=0 ; n<N ; ++n ) {
lldiv_t q { n, 0 };
for( long long i=v.size()-1 ; 0<=i ; --i ) {
q = div( q.quot, v[i].size() );
u[i] = v[i][q.rem];
}
// Do what you want here with u.
for( int x : u ) cout << x << ' ';
cout << '\n';
}
}
int main() {
vector<vector<int> > v { { 1, 2, 3 },
{ 4, 5 },
{ 6, 7, 8 } };
cartesian(v);
return 0;
}
Output:
1 4 6
1 4 7
1 4 8
...
3 5 8
Shorter code:
vector<vector<int>> cart_product (const vector<vector<int>>& v) {
vector<vector<int>> s = {{}};
for (const auto& u : v) {
vector<vector<int>> r;
for (const auto& x : s) {
for (const auto y : u) {
r.push_back(x);
r.back().push_back(y);
}
}
s = move(r);
}
return s;
}
Seems like you'd want a vector of iterators which iterate over your individual vector<int>s.
Start all of the iterators at the beginning. Construct your first product vector by pulling out the element of each vector via the iterator.
Increment the rightmost one, and repeat.
When you reach the end, reset that one to the beginning and increment the next-to-last one. You can get the "next-to-last" iterator by pulling it out of the neighboring element in your vector of iterators.
Continue cycling through until both the last and next-to-last iterators are at the end. Then, reset them both, increment the third-from-last iterator. In general, this can be cascaded.
It's like an odometer, but with each different digit being in a different base.
Here's my solution. Also iterative, but a little shorter than the above...
void xp(const vector<vector<int>*>& vecs, vector<vector<int>*> *result) {
vector<vector<int>*>* rslts;
for (int ii = 0; ii < vecs.size(); ++ii) {
const vector<int>& vec = *vecs[ii];
if (ii == 0) {
// vecs=[[1,2],...] ==> rslts=[[1],[2]]
rslts = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) {
vector<int>* v = new vector<int>;
v->push_back(vec[jj]);
rslts->push_back(v);
}
} else {
// vecs=[[1,2],[3,4],...] ==> rslts=[[1,3],[1,4],[2,3],[2,4]]
vector<vector<int>*>* tmp = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) { // vec[jj]=3 (first iter jj=0)
for (vector<vector<int>*>::const_iterator it = rslts->begin();
it != rslts->end(); ++it) {
vector<int>* v = new vector<int>(**it); // v=[1]
v->push_back(vec[jj]); // v=[1,3]
tmp->push_back(v); // tmp=[[1,3]]
}
}
for (int kk = 0; kk < rslts->size(); ++kk) {
delete (*rslts)[kk];
}
delete rslts;
rslts = tmp;
}
}
result->insert(result->end(), rslts->begin(), rslts->end());
delete rslts;
}
I derived it with some pain from a haskell version I wrote:
xp :: [[a]] -> [[a]]
xp [] = []
xp [l] = map (:[]) l
xp (h:t) = foldr (\x acc -> foldr (\l acc -> (x:l):acc) acc (xp t)) [] h
Since I needed the same functionality, I implemented an iterator which computes the Cartesian product on the fly, as needed, and iterates over it.
It can be used as follows.
#include <forward_list>
#include <iostream>
#include <vector>
#include "cartesian.hpp"
int main()
{
// Works with a vector of vectors
std::vector<std::vector<int>> test{{1,2,3}, {4,5,6}, {8,9}};
CartesianProduct<decltype(test)> cp(test);
for(auto const& val: cp) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
// Also works with something much less, like a forward_list of forward_lists
std::forward_list<std::forward_list<std::string>> foo{{"boo", "far", "zab"}, {"zoo", "moo"}, {"yohoo", "bohoo", "whoot", "noo"}};
CartesianProduct<decltype(foo)> bar(foo);
for(auto const& val: bar) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
}
The file cartesian.hpp looks like this.
#include <cassert>
#include <limits>
#include <stdexcept>
#include <vector>
#include <boost/iterator/iterator_facade.hpp>
//! Class iterating over the Cartesian product of a forward iterable container of forward iterable containers
template<typename T>
class CartesianProductIterator : public boost::iterator_facade<CartesianProductIterator<T>, std::vector<typename T::value_type::value_type> const, boost::forward_traversal_tag>
{
public:
//! Delete default constructor
CartesianProductIterator() = delete;
//! Constructor setting the underlying iterator and position
/*!
* \param[in] structure The underlying structure
* \param[in] pos The position the iterator should be initialized to. std::numeric_limits<std::size_t>::max()stands for the end, the position after the last element.
*/
explicit CartesianProductIterator(T const& structure, std::size_t pos);
private:
//! Give types more descriptive names
// \{
typedef T OuterContainer;
typedef typename T::value_type Container;
typedef typename T::value_type::value_type Content;
// \}
//! Grant access to boost::iterator_facade
friend class boost::iterator_core_access;
//! Increment iterator
void increment();
//! Check for equality
bool equal(CartesianProductIterator<T> const& other) const;
//! Dereference iterator
std::vector<Content> const& dereference() const;
//! The part we are iterating over
OuterContainer const& structure_;
//! The position in the Cartesian product
/*!
* For each element of structure_, give the position in it.
* The empty vector represents the end position.
* Note that this vector has a size equal to structure->size(), or is empty.
*/
std::vector<typename Container::const_iterator> position_;
//! The position just indexed by an integer
std::size_t absolutePosition_ = 0;
//! The begin iterators, saved for convenience and performance
std::vector<typename Container::const_iterator> cbegins_;
//! The end iterators, saved for convenience and performance
std::vector<typename Container::const_iterator> cends_;
//! Used for returning references
/*!
* We initialize with one empty element, so that we only need to add more elements in increment().
*/
mutable std::vector<std::vector<Content>> result_{std::vector<Content>()};
//! The size of the instance of OuterContainer
std::size_t size_ = 0;
};
template<typename T>
CartesianProductIterator<T>::CartesianProductIterator(OuterContainer const& structure, std::size_t pos) : structure_(structure)
{
for(auto & entry: structure_) {
cbegins_.push_back(entry.cbegin());
cends_.push_back(entry.cend());
++size_;
}
if(pos == std::numeric_limits<std::size_t>::max() || size_ == 0) {
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
// Initialize with all cbegin() position
position_.reserve(size_);
for(std::size_t i = 0; i != size_; ++i) {
position_.push_back(cbegins_[i]);
if(cbegins_[i] == cends_[i]) {
// Empty member, so Cartesian product is empty
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
}
// Increment to wanted position
for(std::size_t i = 0; i < pos; ++i) {
increment();
}
}
template<typename T>
void CartesianProductIterator<T>::increment()
{
if(absolutePosition_ == std::numeric_limits<std::size_t>::max()) {
return;
}
std::size_t pos = size_ - 1;
// Descend as far as necessary
while(++(position_[pos]) == cends_[pos] && pos != 0) {
--pos;
}
if(position_[pos] == cends_[pos]) {
assert(pos == 0);
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
// Set all to begin behind pos
for(++pos; pos != size_; ++pos) {
position_[pos] = cbegins_[pos];
}
++absolutePosition_;
result_.emplace_back();
}
template<typename T>
std::vector<typename T::value_type::value_type> const& CartesianProductIterator<T>::dereference() const
{
if(absolutePosition_ == std::numeric_limits<std::size_t>::max()) {
throw new std::out_of_range("Out of bound dereference in CartesianProductIterator\n");
}
auto & result = result_[absolutePosition_];
if(result.empty()) {
result.reserve(size_);
for(auto & iterator: position_) {
result.push_back(*iterator);
}
}
return result;
}
template<typename T>
bool CartesianProductIterator<T>::equal(CartesianProductIterator<T> const& other) const
{
return absolutePosition_ == other.absolutePosition_ && structure_ == other.structure_;
}
//! Class that turns a forward iterable container of forward iterable containers into a forward iterable container which iterates over the Cartesian product of the forward iterable containers
template<typename T>
class CartesianProduct
{
public:
//! Constructor from type T
explicit CartesianProduct(T const& t) : t_(t) {}
//! Iterator to beginning of Cartesian product
CartesianProductIterator<T> begin() const { return CartesianProductIterator<T>(t_, 0); }
//! Iterator behind the last element of the Cartesian product
CartesianProductIterator<T> end() const { return CartesianProductIterator<T>(t_, std::numeric_limits<std::size_t>::max()); }
private:
T const& t_;
};
If someone has comments how to make it faster or better, I'd highly appreciate them.
I was just forced to implement this for a project I was working on and I came up with the code below. It can be stuck in a header and it's use is very simple but it returns all of the combinations you can get from a vector of vectors. The array that it returns only holds integers. This was a conscious decision because I just wanted the indices. In this way, I could index into each of the vector's vector and then perform the calculations I/anyone would need... best to avoid letting CartesianProduct hold "stuff" itself, it is a mathematical concept based around counting not a data structure. I'm fairly new to c++ but this was tested in a decryption algorithm pretty thoroughly. There is some light recursion but overall this is a simple implementation of a simple counting concept.
// Use of the CartesianProduct class is as follows. Give it the number
// of rows and the sizes of each of the rows. It will output all of the
// permutations of these numbers in their respective rows.
// 1. call cp.permutation() // need to check all 0s.
// 2. while cp.HasNext() // it knows the exit condition form its inputs.
// 3. cp.Increment() // Make the next permutation
// 4. cp.permutation() // get the next permutation
class CartesianProduct{
public:
CartesianProduct(int num_rows, vector<int> sizes_of_rows){
permutation_ = new int[num_rows];
num_rows_ = num_rows;
ZeroOutPermutation();
sizes_of_rows_ = sizes_of_rows;
num_max_permutations_ = 1;
for (int i = 0; i < num_rows; ++i){
num_max_permutations_ *= sizes_of_rows_[i];
}
}
~CartesianProduct(){
delete permutation_;
}
bool HasNext(){
if(num_permutations_processed_ != num_max_permutations_) {
return true;
} else {
return false;
}
}
void Increment(){
int row_to_increment = 0;
++num_permutations_processed_;
IncrementAndTest(row_to_increment);
}
int* permutation(){
return permutation_;
}
int num_permutations_processed(){
return num_permutations_processed_;
}
void PrintPermutation(){
cout << "( ";
for (int i = 0; i < num_rows_; ++i){
cout << permutation_[i] << ", ";
}
cout << " )" << endl;
}
private:
int num_permutations_processed_;
int *permutation_;
int num_rows_;
int num_max_permutations_;
vector<int> sizes_of_rows_;
// Because CartesianProduct is called first initially with it's values
// of 0 and because those values are valid and important output
// of the CartesianProduct we increment the number of permutations
// processed here when we populate the permutation_ array with 0s.
void ZeroOutPermutation(){
for (int i = 0; i < num_rows_; ++i){
permutation_[i] = 0;
}
num_permutations_processed_ = 1;
}
void IncrementAndTest(int row_to_increment){
permutation_[row_to_increment] += 1;
int max_index_of_row = sizes_of_rows_[row_to_increment] - 1;
if (permutation_[row_to_increment] > max_index_of_row){
permutation_[row_to_increment] = 0;
IncrementAndTest(row_to_increment + 1);
}
}
};
#include <iostream>
#include <vector>
void cartesian (std::vector<std::vector<int>> const& items) {
auto n = items.size();
auto next = [&](std::vector<int> & x) {
for ( int i = 0; i < n; ++ i )
if ( ++x[i] == items[i].size() ) x[i] = 0;
else return true;
return false;
};
auto print = [&](std::vector<int> const& x) {
for ( int i = 0; i < n; ++ i )
std::cout << items[i][x[i]] << ",";
std::cout << "\b \n";
};
std::vector<int> x(n);
do print(x); while (next(x)); // Shazam!
}
int main () {
std::vector<std::vector<int>>
items { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
cartesian(items);
return 0;
}
The idea behind this is as follows.
Let n := items.size().
Let m_i := items[i].size(), for all i in {0,1,...,n-1}.
Let M := {0,1,...,m_0-1} x {0,1,...,m_1-1} x ... x {0,1,...,m_{n-1}-1}.
We first solve the simpler problem of iterating through M. This is accomplished by the next lambda. The algorithm is simply the "carrying" routine grade schoolers use to add 1, albeit with a mixed radix number system.
We use this to solve the more general problem by transforming a tuple x in M to one of the desired tuples via the formula items[i][x[i]] for all i in {0,1,...,n-1}. We perform this transformation in the print lambda.
We then perform the iteration with do print(x); while (next(x));.
Now some comments on complexity, under the assumption that m_i > 1 for all i:
This algorithm requires O(n) space. Note that explicit construction of the Cartesian product takes O(m_0 m_1 m_2 ... m_{n-1}) >= O(2^n) space. So this is exponentially better on space than any algorithm which requires all tuples to be stored simultaneously in memory.
The next function takes amortized O(1) time (by a geometric series argument).
The print function takes O(n) time.
Hence, altogether, the algorithm has time complexity O(n|M|) and space complexity O(n) (not counting the cost of storing items).
An interesting thing to note is that if print is replaced with a function which inspects on average only O(1) coordinates per tuple rather than all of them, then time complexity falls to O(|M|), that is, it becomes linear time with respect to the size of the Cartesian product. In other words, avoiding the copy of the tuple each iterate can be meaningful in some situations.
This version supports no iterators or ranges, but it is a simple direct implementation that uses the multiplication operator to represent the Cartesian product, and a lambda to perform the action.
The interface is designed with the particular functionality I needed. I needed the flexibility to choose vectors over which to apply the Cartesian product in a way that did not obscure the code.
int main()
{
vector< vector<long> > v{ { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
(Cartesian<long>(v[0]) * v[1] * v[2]).ForEach(
[](long p_Depth, long *p_LongList)
{
std::cout << p_LongList[0] << " " << p_LongList[1] << " " << p_LongList[2] << std::endl;
}
);
}
The implementation uses recursion up the class structure to implement the embedded for loops over each vector. The algorithm works directly on the input vectors, requiring no large temporary arrays. It is simple to understand and debug.
The use of std::function p_Action instead of void p_Action(long p_Depth, T *p_ParamList) for the lambda parameter would allow me to capture local variables, if I wanted to. In the above call, I don't.
But you knew that, didn't you. "function" is a template class which takes the type parameter of a function and makes it callable.
#include <vector>
#include <iostream>
#include <functional>
#include <string>
using namespace std;
template <class T>
class Cartesian
{
private:
vector<T> &m_Vector;
Cartesian<T> *m_Cartesian;
public:
Cartesian(vector<T> &p_Vector, Cartesian<T> *p_Cartesian=NULL)
: m_Vector(p_Vector), m_Cartesian(p_Cartesian)
{};
virtual ~Cartesian() {};
Cartesian<T> *Clone()
{
return new Cartesian<T>(m_Vector, m_Cartesian ? m_Cartesian->Clone() : NULL);
};
Cartesian<T> &operator *=(vector<T> &p_Vector)
{
if (m_Cartesian)
(*m_Cartesian) *= p_Vector;
else
m_Cartesian = new Cartesian(p_Vector);
return *this;
};
Cartesian<T> operator *(vector<T> &p_Vector)
{
return (*Clone()) *= p_Vector;
};
long Depth()
{
return m_Cartesian ? 1 + m_Cartesian->Depth() : 1;
};
void ForEach(function<void (long p_Depth, T *p_ParamList)> p_Action)
{
Loop(0, new T[Depth()], p_Action);
};
private:
void Loop(long p_Depth, T *p_ParamList, function<void (long p_Depth, T *p_ParamList)> p_Action)
{
for (T &element : m_Vector)
{
p_ParamList[p_Depth] = element;
if (m_Cartesian)
m_Cartesian->Loop(p_Depth + 1, p_ParamList, p_Action);
else
p_Action(Depth(), p_ParamList);
}
};
};

Using STL/Boost to find and modify matching elements in a vector

Let's say I have a vector declared like this:
struct MYSTRUCT
{
float a;
float b;
};
std::vector<MYSTRUCT> v;
Now, I want to find all elements of v that share the same a, and average their b, i.e.
Say v contains these five elements {a, b}: {1, 1}, {1, 2}, {2, 1}, {1, 3}, {2, 2}
I want to get v[0], v[1], v[3] (where a is 1) and average b: (1 + 2 + 3)/3 = 2, and v[2] and v[4] (where a is 2) and average b: (1+2)/2 = 1.5
Afterwards v will look like this: {1, 2}, {1, 2}, {2, 1.5}, {1, 2}, {2, 1.5}
I'm not really familiar with STL or Boost so I can only figure out how to do this the "bruteforce" way in C++, but I'm guessing that the STL (for_each?) and Boost (lambda?) libraries can solve this more elegantly.
EDIT Just for reference, here's my (working) brute force way to do it:
for(int j = 0; j < tempV.size(); j++)
{
MYSTRUCT v = tempV.at(j);
int matchesFound = 0;
for(int k = 0; k < tempV.size(); k++)
{
if(k != j && v.a == tempV.at(k).a)
{
v.b += tempV.at(k).b;
matchesFound++;
}
}
if(matchesFound > 0)
{
v.b = v.b/matchesFound;
}
finalV.push_back(v);
}
Just thinking aloud, this may end up fairly silly:
struct Average {
Average() : total(0), count(0) {}
operator float() const { return total / count; }
Average &operator+=(float f) {
total += f;
++count;
}
float total;
int count;
};
struct Counter {
Counter (std::map<int, Average> &m) : averages(&m) {}
Counter operator+(const MYSTRUCT &s) {
(*averages)[s.a] += s.b;
return *this;
}
std::map<int, Average> *averages;
};
std::map<int, Average> averages;
std::accumulate(v.begin(), v.end(), Counter(averages));
BOOST_FOREACH(MYSTRUCT &s, v) {
s.b = averages[s.a];
}
Hmm. Not completely silly, but perhaps not compelling either...
Sketch of a solution:
sort(v.begin(), v.end());
vector<MYSTRUCT>::iterator b = v.begin(), e = v.end();
while (b != e) {
vector<MYSTRUCT>::iterator m = find_if(b, e, bind(&MYSTRUCT::a, _1) != b->a);
float x = accumulate(b, m, 0.f, _1 + bind(&MYSTRUCT::b,_2)) / (m-b);
for_each(b, m, bind(&MYSTRUCT::a, _1) = x);
b = m;
}
It's not a great one, though, since it's not exactly what was asked for (thanks to the sort), and still doesn't really feel clean to me. I think that some filter_iterators and transform_iterators or something could possibly give a much more functional-style answer.
Another approach, this one not in-place, though I think it's time-complexity-wise asymptotically the same.
typedef map<float, vector<float>> map_type;
map_type m;
BOOST_FOREACH(MYSTRUCT const &s, v) {
m[s.a].push_back(s.b);
}
BOOST_FOREACH(map_type::reference p, m) {
float x = accumulate(p.second.begin(), p.second.end(), 0.0f) / p.second.size();
p.second.assign(1, x);
}
BOOST_FOREACH(MYSTRUCT &s, v) {
s.b = m[s.a].front();
}
Again, though, it's just a slightly elegant way to code the brute-force solution, not a nice functional-style way.
Perhaps a brute force approach?...
struct MYAVG
{
int count;
float avg;
};
// first pass - calculate averages
for ( vector < MYSTRUCT >::iterator first = v.begin();
first != v.end(); ++first )
{
MYAVG myAvg;
myAvg.count = 1;
myAvg.avg = first->b;
if ( mapAvg.find( first->a ) == mapAvg.end() )
mapAvg[ first->a ] = myAvg;
else
{
mapAvg[ first->a ].count++;
mapAvg[ first->a ].avg =
( ( mapAvg[ first->a ].avg * ( mapAvg[ first->a ].count - 1 ) )
+ myAvg.avg ) / mapAvg[ first->a ].count;
}
}
// second pass - update average values
for ( vector < MYSTRUCT >::iterator second = v.begin();
second != v.end(); ++second )
second->b = mapAvg[ second->a ].avg;
I've tested this with the values you've supplied and get the required vector - It's not exactly optimal, but I think it's quite easy to follow (might be more preferable to a complex algorithm).
Avoid C-style! It's not what C++ is designed for. I'd like to emphasize clarity and readability.
#include <algorithm>
#include <iostream>
#include <map>
#include <numeric>
#include <vector>
#include <boost/assign/list_of.hpp>
using namespace std;
using namespace boost::assign;
struct mystruct
{
mystruct(float a, float b)
: a(a), b(b)
{ }
float a;
float b;
};
vector <mystruct> v =
list_of ( mystruct(1, 1) ) (1, 2) (2, 1) (1, 3) (2, 2);
ostream& operator<<(
ostream& out, mystruct const& data)
{
out << "{" << data.a << ", " << data.b << "}";
return out;
}
ostream& operator<<(
ostream& out, vector <mystruct> const& v)
{
copy(v.begin(), v.end(),
ostream_iterator <mystruct> (out, " "));
return out;
}
struct average_b
{
map <float, float> sum;
map <float, int> count;
float operator[] (float a) const
{
return sum.find(a)->second / count.find(a)->second;
}
};
average_b operator+ (
average_b const& average,
mystruct const& s)
{
average_b result( average );
result.sum[s.a] += s.b;
++result.count[s.a];
return result;
}
struct set_b_to_average
{
set_b_to_average(average_b const& average)
: average(average)
{ }
mystruct operator()(mystruct const& s) const
{
return mystruct(s.a, average[s.a]);
}
average_b const& average;
};
int main()
{
cout << "before:" << endl << v << endl << endl;
transform(v.begin(), v.end(),
v.begin(), set_b_to_average(
accumulate(v.begin(), v.end(), average_b())
));
cout << "after:" << endl << v << endl << endl;
}
You can use the "partition" algorithm along with "accumulate."
Example
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
struct test
{
float a;
float b;
test(const float one, const float two)
: a(one), b(two)
{
}
};
struct get_test_a {
float interesting;
get_test_a(const float i)
: interesting(i)
{
}
bool operator()(const test &value) const
{
static const float epi = 1e-6;
return value.a < interesting + epi &&
value.a > interesting - epi;
}
};
struct add_test_b {
float operator()(const float init, const test &value) const
{
return init + value.b;
}
};
int main(int argc, char **argv)
{
using std::partition;
using std::accumulate;
using std::distance;
typedef std::vector<test> container;
container myContainer;
// Say 'myVector' contains these five elements {a, b}:
// {1, 1}, {1, 2}, {2, 1}, {1, 3}, {2, 2}
myContainer.push_back(test(1, 1));
myContainer.push_back(test(1, 2));
myContainer.push_back(test(2, 1));
myContainer.push_back(test(1, 3));
myContainer.push_back(test(2, 2));
// I want to get v[0], v[1], v[3] (where a is 1) and
// average b: (1 + 2 + 3)/3 = 2,
// and v[2] and v[4] (where a is 2) and average b: (1+2)/2 = 1.5
const container::iterator split =
partition(myContainer.begin(), myContainer.end(),
get_test_a(1));
const float avg_of_one =
accumulate(myContainer.begin(), split, 0.0f, add_test_b())
/ distance(myContainer.begin(), split);
const float avg_of_others =
accumulate(split, myContainer.end(), 0.0f, add_test_b())
/ distance(split, myContainer.end());
std::cout << "The 'b' average of test values where a = 1 is "
<< avg_of_one << std::endl;
std::cout << "The 'b' average of the remaining test values is "
<< avg_of_others << std::endl;
return 0;
}
Documentation from the gcc headers
/**
* #brief Move elements for which a predicate is true to the beginning
* of a sequence.
* #ingroup mutating_algorithms
* #param first A forward iterator.
* #param last A forward iterator.
* #param pred A predicate functor.
* #return An iterator #p middle such that #p pred(i) is true for each
* iterator #p i in the range #p [first,middle) and false for each #p i
* in the range #p [middle,last).
*
* #p pred must not modify its operand. #p partition() does not preserve
* the relative ordering of elements in each group, use
* #p stable_partition() if this is needed.
*/
template<typename _ForwardIterator, typename _Predicate>
inline _ForwardIterator
partition(_ForwardIterator __first, _ForwardIterator __last,
_Predicate __pred)
/**
* #brief Accumulate values in a range with operation.
*
* Accumulates the values in the range [first,last) using the function
* object #a binary_op. The initial value is #a init. The values are
* processed in order.
*
* #param first Start of range.
* #param last End of range.
* #param init Starting value to add other values to.
* #param binary_op Function object to accumulate with.
* #return The final sum.
*/
template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
inline _Tp
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
_BinaryOperation __binary_op)
It seems the easiest way is to run a moderately complex functor over the colelction:
struct CountAllAverages {
typedef std::pair<float, unsigned> average_t;
std::map<float, average_t> averages;
void operator()(mystruct& ms) {
average_t& average = averages[ms.a];
average.second++;
average.first += ms.b;
}
float getAverage(float a) { return averages[a].first/averages[a].second; }
};
Writing C++, you should maintain balance between reusability (e.g. reuse existing algorithms and data structures) and readability. onebyone was close, but his solution can be further improved:
template<class T>
struct average {
T total;
int count;
mutable bool calculated;
mutable T average_value;
average & operator+=(T const & value) {
total += value;
++count;
calculated = false;
}
T value() const {
if(!calculated) {
calculated = true;
average_value = total / count;
}
return average_value;
}
};
std::map< float, average<float> > averages;
BOOST_FOREACH(MYSTRUCT &element, v) {
averages[element.a] += element.b;
}
BOOST_FOREACH(MYSTRUCT &element, v) {
element.b = averages[element.a].value();
}
Bonus points for having reusable "average" type.
struct MYSTRUCT {
float x;
float y;
operator float() const { return y; }
};
class cmp {
float val;
public:
cmp(float v) : val(v) {}
bool operator()(MYSTRUCT const &a) { return a.x != val; }
};
float masked_mean(std::vector<MYSTRUCT> const &in, MYSTRUCT const &mask) {
std::vector<float> temp;
std::remove_copy_if(in.begin(), in.end(), std::back_inserter(temp), cmp(mask.x));
return std::accumulate(temp.begin(), temp.end(), 0.0f) / temp.size();
}