chhenning
chhenning

Reputation: 2077

Generating tuples from a vector ( General Algorithm )

Imagine we have a vector with only unique values and would like to generate all pairs. The algorithm to do so is:

vector< int > data;
// ... pushback some data

vector< vector< int > > pairs;

for( size_t i = 0; i < data.size() - 1; ++i )
{
    for( size_t j = i + 1; j < data.size(); ++j )
    {
        vector< int > pair; 
        pair.push_back( data[i] ); 
        pair.push_back( data[j] );

        pairs.push_back( pair );
    }
}

Now, for triples the algorithm changes to:

vector< int > data;
// ... pushback some data

vector< vector< int > > triples;

for( size_t i = 0; i < data.size() - 2; ++i )
{
    for( size_t j = i + 1; j < data.size() - 1; ++j )
    {
        for( size_t k = j + 1; k < data.size(); ++k )
        {
            vector< int > triple; 
            triple.push_back( data[i] ); 
            triple.push_back( data[j] );
            triple.push_back( data[k] );

            triples.push_back( triple );
        }
    }
}

It's fairly easy to come up with the code for quadruples and other tuple types.

Could someone show me how to achieve a general algorithm to generate all sort of tuples? And since we are at it how can I calculate the number of tuples given the number of elements in a vector? For pairs the formula is n(n-1)/2.

Thanks!

Upvotes: 2

Views: 319

Answers (1)

Agentlien
Agentlien

Reputation: 5136

What you are describing is called k-combinations, which is a very important concept in the area of combinatorics. The number of unique combinations of k elements from a set of n elements is expressed by the formula n! /(k!(n-k)!).

To solve this efficiently in a generic way, you should probably look into std::tuple and variadic templates (a C++11 feature). If you do not know the dimensionality at compile-time, however, you'll have to create a recursive function which takes two arguments: a list of all items and k, the number items to choose from the list.

Then, for each element e in the set, create a list containing that element and the result of calling the function recursively with k-1 as number to choose and supplying only the elements of the list which come after e in the list. This will prevent creating the same subset in multiple sub-trees of the recursion.

Hope that's clear enough for you. :) If you have any more questions, feel free to ask for more explanations.

Upvotes: 2

Related Questions