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\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.