I have several data that looks like this:
Vector1_elements = T,C,A
Vector2_elements = C,G,A
Vector3_elements = C,G,T
..... up to ...
VectorK_elements = ...
I too am interested in building some sort of easy to rinse and repeat combinatorial. I am familiar with the odometer driven type approach, if you will, where you've got walking indices. Something along those lines. The point is, to easily build out the tuples across an arbitrary set of unrelated vectors.
This does not quite answer your question, I don't think, but you could build static/design time combinations using a variadic production such as the following, where T1-3 are arbitrary types:
template<class V>
void push_back_tupled_combos(V& v) {
// Variadic no-args no-op
}
template<class V, typename A, typename B, typename C, typename... Args>
void push_back_tupled_combos(V& v, A a, B b, C c, Args... args) {
v.push_back({ a, b, c });
push_back_tupled_combos(v, args...);
}
template<class V, typename... Args>
void push_back_tupled_combos(V& v, Args... args) {
}
Assuming you've got a vector that looks something like this:
typedef vector<tuple<T1, T2, T3>> CombosVector;
CombosVector combos;
push_back_tupled_combos(combos
, 1, 2, 3
, 4, 5, 6
, 7, 8, 9, ...);
Like I said, this is a design time consideration. It does not build tuples across a run time range of vectors. That's the down side. The up side, however, is that you gain compile time comprehension of your vectored tuples.
Again, not quite what you, or even I, are after, but maybe it helps spark favorable feedback.
The basic difficulty with recursion here is that you need to keep track of the entire list of indices (or else construct the string incrementally, as another question points out).
An expedient way to handle this problem without constructing additional objects inside the loops is to hand your recursive function a vector of indices, of the same length as the vector of vectors:
void printcombos(const vector<vector<string> >&vec,vector<int>&index,int depth) {
if(depth==index.length()) {
for(int i=0; i<depth; ++i) {
cout<<vec[i][index[i]];
}
cout<<endl;
} else {
const vector<string> &myvec= vec[depth];
int mylength= myvec.length();
for(int i=0; i<mylength; ++i) {
index[depth]=i;
printcombos(vec,index,depth+1);
}
}
}
Combining three vectors is essentially the same as first combining two vectors, and then combining the third one with the result.
So it all boils down to writing a function that can combine two vectors.
std::vector< std::string > combine(std::vector< std::string > const & inLhs, std::vector< std::string > const & inRhs) {
std::vector< std::string > result;
for (int i=0; i < inLhs.size(); ++i) {
for (int j=0; j < inRhs.size(); ++j) {
result.push_back(inLhs[i] + inRhs[j]);
}
}
return result;
}
And then something like:
std::vector< std::string > result = combine(Vec1, Vec2);
result = combine(result, Vec3);
and so on for every vector you need combined.
Note that it's more the "C++ way" to use input and output iterators i.s.o. passing vectors around, and much more efficient. In the above version the vector gets copied over and over...
I simply used vectors to stay closer to your original code and, hopefully, make more sense to you.
Use next_permutation function implemented in std of stl