
#include <iostream>
#include <algorithm>
#include <vector>

namespace stable {
    template<class T>
    void iter_swap(T a, T b)
    {
        T lo = std::min(a, b);
        T hi = std::max(a, b);

        if (*lo != *hi) {
            auto loval = *lo;
            auto hival = *hi;

            for (auto it = lo + 1; it < hi; ++it) {
                if (loval == *it) {
                    std::swap(loval, *it);
                }
            }

            for (auto it = hi; it-- > lo; ) {
                if (hival == *it) {
                    std::swap(hival, *it);
                }
            }

            *lo = hival;
            *hi = loval;
        }
    }

    template<class T>
    void reverse(T first, T last)
    {
        while (first != last && first != --last) {
            stable::iter_swap(first++, last);
        }
    }
    

    template<class T>
    bool next_permutation(T first, T last)
    {
        auto r_first = std::make_reverse_iterator(last);
        auto r_last = std::make_reverse_iterator(first);
        auto left = std::is_sorted_until(r_first, r_last);

        if (left != r_last){
            auto right = std::upper_bound(r_first, left, *left);
            stable::iter_swap(left, right);
        }

        stable::reverse(left.base(), last);

        return left != r_last;
    }
}

/*
 *      A wrapper around a string that compares the first letter only
 */
struct Stringlet {
    std::string str;
    
    bool operator <(const Stringlet& other) const
    {
        return (str[0] < other.str[0]);
    }
    
    bool operator ==(const Stringlet& other) const
    {
        return (str[0] == other.str[0]);
    }
    
    bool operator !=(const Stringlet& other) const
    {
        return (str[0] != other.str[0]);
    }
};

std::ostream& operator<<(std::ostream& os, const Stringlet& s)
{
    os << s.str;
    return os;
}

template<class T>
void put(std::ostream& os, T first, T last)
{
    size_t n = 0;
    os << "[";
    
    while (first < last) {
        if (n++) os << ", ";
        os << *first++;
    }
    
    os << "]\n";
}

int main(void)
{
    Stringlet orig[] = {"1 ", "11", "2 ", "22", "2\"", "3 "};
    size_t n = 4;

    std::vector<Stringlet> pool;
    
    for (size_t i = 0; i < n; i++) {
        pool.push_back(orig[i]);
    }
    
    do {
        put(std::cout, pool.begin(), pool.end());
    } while (stable::next_permutation(pool.begin(), pool.end()));

    return 0;
}
