#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <string>

std::string as_string(const std::vector<char>& vals, const std::vector<bool>& pattern)
{
    std::string result;

    for (unsigned i = 0; i < pattern.size(); ++i)
        if (pattern[i])
            result += vals[i];

    return result;
}

// Note: Only good for values greater than 0 and less than 10.
std::vector<std::string> unique_combinations(unsigned val)
{
    std::vector<std::string> result;

    std::vector<char> vals(val);
    std::iota(vals.begin(), vals.end(), '1');

    std::vector<bool> pattern(vals.size(), false);

    for (auto it = pattern.rbegin(); it != pattern.rend(); ++it)
    {
        *it = true;

        do
        {
            result.emplace_back(as_string(vals, pattern));
        } while (std::next_permutation(pattern.begin(), pattern.end()));
    }

    return result;
}

int main()
{
    for (unsigned i = 1; i < 6; ++i)
    {

        auto combos = unique_combinations(i);
 
        // to present them in the same order as the sample
        auto ordering = [](const std::string& a, const std::string& b)
        {
            if (a.size() < b.size())
                return true;

            if (a.size() > b.size())
                return false;

            return a < b;
        };

        std::sort(combos.begin(), combos.end(), ordering);

        auto combo = combos.begin();
        while (combo != combos.end())
        {
            unsigned size = combo->size();
            std::cout << *combo;

            while (++combo != combos.end() && combo->size() == size)
                std::cout << ", " << *combo;
            
            std::cout << '\n';
        }

        std::cout << '\n';
    }
}