#include <random>
#include <vector>
#include <string>
#include <set>
#include <iostream>
#include <algorithm>

using namespace std;

template <int n>
struct permutation {
    // prefer 1-based indices
    permutation() { for (int i = 0; i <= n; ++i) v_.push_back(i); }

    static constexpr int size() { return n; }

    static permutation  id() { return permutation(); }
    static permutation  loop(const vector<int> idx) {
        permutation res;
        for (int i = 0; i + 1 < idx.size(); ++i)
            res.v_[idx[i]] = idx[i + 1];
        res.v_[*idx.rbegin()] = idx[0];
        return res;
    }

    const vector<int>&  data() const { return v_; }
    int                 operator[](int i) const { return v_[i]; }
    bool                operator==(const permutation& r) const { return v_ == r.v_; }
    bool                operator<(const permutation& r) const { return v_ < r.v_; }

    permutation         operator*(const permutation& r) const {
        permutation res;
        for (int i = 1; i <= n; ++i)
            res.v_[i] = (*this)[r[i]];
        return res;
    }
    permutation         inv() const {
        permutation res;
        for (int i = 1; i <= n; ++i)
            res.v_[v_[i]] = i;
        return res;
    }

private:
    vector<int> v_;
};

// Helpers
// commutator
template<int n>
permutation<n>
commutator(const permutation<n>& a, const permutation<n>& b) {
    return a*b*a.inv()*b.inv();
}

// Serialization
template <int n>
string asLoops(const permutation<n>& p, bool includeFixedPoints = false) {
    
    string res;
    set<int> processed;
    for (int start = 1; start <= n; ++start) {
        if (processed.count(start) > 0)
            continue;
        if (p[start] == start && !includeFixedPoints)
            continue;
        
        res += "(";
        int cur = start;
        do {
            processed.insert(cur);

            res += to_string(cur);
            cur = p[cur];
            if (cur != start)
                res += " ";
        } while (cur != start);
        res += ")";
    }
    return res.empty() ? "id" : res;
}
//---------------------------------------------
namespace problem15 {

typedef permutation<15> perm;

perm loop(int middle, int start) {
    vector<int> v;
    for (int i = start; i <= 2*middle - start; ++i)
        v.push_back(i);
    return perm::loop(v);
}

} // ns problem15

//---------------------------------------------
int main()
{
    namespace p15 = problem15;
    set<p15::perm> generatedCmts;
    int generatedCount = 0;
    
    for (int middle = 4; middle < 16; middle += 4)
        for (int start = middle - 3; start < middle; ++start)
            for (int middle2 = 4; middle2 < 16; middle2 += 4)
                for (int start2 = middle2 - 3; start2 < middle2; ++start2) {

                    p15::perm p1 = p15::loop(middle, start);
                    p15::perm p2 = p15::loop(middle2, start2);
                    
                    p15::perm cmt = commutator(p1, p2);

                    if (generatedCmts.count(cmt) > 0 || generatedCmts.count(cmt.inv()) > 0)
                        continue;
                    if (cmt == p15::perm::id())
                        continue;
                    generatedCmts.insert(cmt);
                    ++generatedCount;

                    string cmtLoops = asLoops(cmt);
                        if (count(cmtLoops.begin(), cmtLoops.end(), '(') == 1) // single loop
                            cout << "[" << asLoops(p1) << ", " << asLoops(p2) << "] = " << asLoops(cmt) << endl;

                }
}
