3
\$\begingroup\$

I've tried out implementing a combination generator using boost coroutines. It accepts an array of possible values and generates one array at a time for each combination. As a limitation, it only generates combinations of the same length as the array of possible values and does not check for duplicates inside the source array.

#include <boost/coroutine/coroutine.hpp>
#include <algorithm>
#include <iostream>

template<typename ItElements, typename ItArray, typename Fn>
void enumerate_combinations(ItElements elements_from, ItElements elements_to, ItArray array_from, ItArray array_to, 
    Fn&& callback)
{
    for (auto it = elements_from; it != elements_to; ++it)
    {
        *array_from = *it;
        if (std::distance(array_from, array_to) > 1)
        {
            enumerate_combinations(elements_from, elements_to, array_from + 1, array_to, callback);
        }
        else
        {
            callback();
        }
    }
}

template<typename T, size_t nr_elements>
auto enumerate_combinations(T(&elements)[nr_elements])
{
    return boost::coroutines::asymmetric_coroutine<T(&)[nr_elements]>::pull_type(
        [&](boost::coroutines::asymmetric_coroutine<T(&)[nr_elements]>::push_type& sink)
    {
        T buffer[nr_elements];
        std::fill(std::begin(buffer), std::end(buffer), elements[0]);

        enumerate_combinations(std::begin(elements), std::end(elements), std::begin(buffer), std::end(buffer), 
            [&]() {sink(buffer);});
    });
}

template<typename T, size_t nr_elements>
std::ostream& print_array(T(&array)[nr_elements], std::ostream& stream, const char* separator = " ")
{
    for (size_t i = 0; i < nr_elements - 1; i++)
    {
        stream << array[i];
        if (separator)
        {
            stream << separator;
        }
    }
    stream << array[nr_elements - 1];
    return stream;
}

int main()
{    
    int digits[] = { 1, 2, 3 };
    for (auto& combination : enumerate_combinations(digits))
    {
        print_array(combination, std::cout) << '\n';
    }
}

Any thoughts or reviews?

Running the above code produces:

1 1 1
1 1 2
1 1 3 
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
2 1 1
2 1 2
2 1 3
2 2 1
2 2 2
2 2 3
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.