#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;
}
}