import std.algorithm;
import std.array;
import std.range;
import std.stdio;
immutable int NA = -1;
auto mult (int [] p, int [] q)
{
auto n = p.length;
auto res = new int [n];
foreach (i; 0..n)
{
if (q[i] != NA)
{
res[i] = p[q[i]];
}
}
return res;
}
void main ()
{
immutable int scale = 2; // 1 for testing, 2 for the actual problem
immutable int n = 14 * scale;
immutable int parts = 2 * scale;
immutable int num1Right = 2 * scale;
immutable int num3Right = 4 * scale;
auto b = n.iota.array;
foreach (j; 0..parts)
{
bringToFront (b[j * 7 + 0..j * 7 + 1],
b[j * 7 + 1..j * 7 + 7]);
}
debug {writeln (b);}
auto bi = new int [n];
foreach (i; 0..n)
{
bi[b[i]] = i;
}
auto ab = new int [n];
ab[] = NA;
auto u = new bool [n];
bool check ()
{
foreach (i; 0..n)
{
if (ab[i] != NA)
{
if (ab[i] == i)
{
return false;
}
if (ab[ab[i]] != NA)
{
if (ab[ab[i]] != i)
{
return false;
}
}
}
}
auto a = mult (ab, bi);
int num1 = 0;
int num3 = 0;
foreach (i; 0..n)
{
if (a[i] != NA)
{
if (a[i] == i)
{
num1 += 1;
if (num1 > num1Right)
{
return false;
}
}
else
{
if (a[a[i]] != NA)
{
if (a[a[i]] == i)
{
return false;
}
else if (a[a[a[i]]] != NA)
{
if (a[a[a[i]]] == i)
{
num3 += 1;
if (num3 > num3Right)
{
return false;
}
}
else
{
return false;
}
}
}
}
}
}
return true;
}
void recur (int k)
{
if (k == n)
{
writeln (ab);
return;
}
auto a = mult (ab, bi);
// debug {writeln (a);}
foreach (i; 0..n)
{
if (a[i] != NA && a[i] != i &&
a[a[i]] != NA)
{
if (a[a[a[i]]] == NA)
{
// a[a[a[i]]] = i;
ab[bi[a[a[i]]]] = i;
a = mult (ab, bi);
assert (a[a[a[i]]] == i);
recur (k);
ab[bi[a[a[i]]]] = NA;
return;
}
}
}
if (ab[k] != NA)
{
recur (k + 1);
return;
}
debug {writeln (ab);}
if (!check ())
{
return;
}
foreach (i; 0..n)
{
if (!u[i])
{
if (i == k || ab[i] != NA)
{
continue;
}
u[i] = true;
ab[k] = i;
ab[i] = k;
recur (k + 1);
ab[i] = NA;
ab[k] = NA;
u[i] = false;
}
}
}
recur (0);
}
aW1wb3J0IHN0ZC5hbGdvcml0aG07CmltcG9ydCBzdGQuYXJyYXk7CmltcG9ydCBzdGQucmFuZ2U7CmltcG9ydCBzdGQuc3RkaW87CgppbW11dGFibGUgaW50IE5BID0gLTE7CgphdXRvIG11bHQgKGludCBbXSBwLCBpbnQgW10gcSkKewoJYXV0byBuID0gcC5sZW5ndGg7CglhdXRvIHJlcyA9IG5ldyBpbnQgW25dOwoJZm9yZWFjaCAoaTsgMC4ubikKCXsKCQlpZiAocVtpXSAhPSBOQSkKCQl7CgkJCXJlc1tpXSA9IHBbcVtpXV07CgkJfQoJfQoJcmV0dXJuIHJlczsKfQoKdm9pZCBtYWluICgpCnsKCWltbXV0YWJsZSBpbnQgc2NhbGUgPSAyOyAvLyAxIGZvciB0ZXN0aW5nLCAyIGZvciB0aGUgYWN0dWFsIHByb2JsZW0KCWltbXV0YWJsZSBpbnQgbiA9IDE0ICogc2NhbGU7CglpbW11dGFibGUgaW50IHBhcnRzID0gMiAqIHNjYWxlOwoJaW1tdXRhYmxlIGludCBudW0xUmlnaHQgPSAyICogc2NhbGU7CglpbW11dGFibGUgaW50IG51bTNSaWdodCA9IDQgKiBzY2FsZTsKCWF1dG8gYiA9IG4uaW90YS5hcnJheTsKCWZvcmVhY2ggKGo7IDAuLnBhcnRzKQoJewoJCWJyaW5nVG9Gcm9udCAoYltqICogNyArIDAuLmogKiA3ICsgMV0sCgkJICAgIGJbaiAqIDcgKyAxLi5qICogNyArIDddKTsKCX0KCWRlYnVnIHt3cml0ZWxuIChiKTt9CglhdXRvIGJpID0gbmV3IGludCBbbl07Cglmb3JlYWNoIChpOyAwLi5uKQoJewoJCWJpW2JbaV1dID0gaTsKCX0KCWF1dG8gYWIgPSBuZXcgaW50IFtuXTsKCWFiW10gPSBOQTsKCWF1dG8gdSA9IG5ldyBib29sIFtuXTsKCglib29sIGNoZWNrICgpCgl7CgkJZm9yZWFjaCAoaTsgMC4ubikKCQl7CgkJCWlmIChhYltpXSAhPSBOQSkKCQkJewoJCQkJaWYgKGFiW2ldID09IGkpCgkJCQl7CgkJCQkJcmV0dXJuIGZhbHNlOwoJCQkJfQoJCQkJaWYgKGFiW2FiW2ldXSAhPSBOQSkKCQkJCXsKCQkJCQlpZiAoYWJbYWJbaV1dICE9IGkpCgkJCQkJewoJCQkJCQlyZXR1cm4gZmFsc2U7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoKCQlhdXRvIGEgPSBtdWx0IChhYiwgYmkpOwoJCWludCBudW0xID0gMDsKCQlpbnQgbnVtMyA9IDA7CgkJZm9yZWFjaCAoaTsgMC4ubikKCQl7CgkJCWlmIChhW2ldICE9IE5BKQoJCQl7CgkJCQlpZiAoYVtpXSA9PSBpKQoJCQkJewoJCQkJCW51bTEgKz0gMTsKCQkJCQlpZiAobnVtMSA+IG51bTFSaWdodCkKCQkJCQl7CgkJCQkJCXJldHVybiBmYWxzZTsKCQkJCQl9CgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJaWYgKGFbYVtpXV0gIT0gTkEpCgkJCQkJewoJCQkJCQlpZiAoYVthW2ldXSA9PSBpKQoJCQkJCQl7CgkJCQkJCQlyZXR1cm4gZmFsc2U7CgkJCQkJCX0KCQkJCQkJZWxzZSBpZiAoYVthW2FbaV1dXSAhPSBOQSkKCQkJCQkJewoJCQkJCQkJaWYgKGFbYVthW2ldXV0gPT0gaSkKCQkJCQkJCXsKCQkJCQkJCQludW0zICs9IDE7CgkJCQkJCQkJaWYgKG51bTMgPiBudW0zUmlnaHQpCgkJCQkJCQkJewoJCQkJCQkJCQlyZXR1cm4gZmFsc2U7CgkJCQkJCQkJfQoJCQkJCQkJfQoJCQkJCQkJZWxzZQoJCQkJCQkJewoJCQkJCQkJCXJldHVybiBmYWxzZTsKCQkJCQkJCX0KCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCgkJcmV0dXJuIHRydWU7Cgl9CgoJdm9pZCByZWN1ciAoaW50IGspCgl7CgkJaWYgKGsgPT0gbikKCQl7CgkJCXdyaXRlbG4gKGFiKTsKCQkJcmV0dXJuOwoJCX0KCQlhdXRvIGEgPSBtdWx0IChhYiwgYmkpOwovLwkJZGVidWcge3dyaXRlbG4gKGEpO30KCQlmb3JlYWNoIChpOyAwLi5uKQoJCXsKCQkJaWYgKGFbaV0gIT0gTkEgJiYgYVtpXSAhPSBpICYmCgkJCSAgICBhW2FbaV1dICE9IE5BKQoJCQl7CgkJCQlpZiAoYVthW2FbaV1dXSA9PSBOQSkKCQkJCXsKLy8JCQkJCWFbYVthW2ldXV0gPSBpOwoJCQkJCWFiW2JpW2FbYVtpXV1dXSA9IGk7CgkJCQkJYSA9IG11bHQgKGFiLCBiaSk7CgkJCQkJYXNzZXJ0IChhW2FbYVtpXV1dID09IGkpOwoJCQkJCXJlY3VyIChrKTsKCQkJCQlhYltiaVthW2FbaV1dXV0gPSBOQTsKCQkJCQlyZXR1cm47CgkJCQl9CgkJCX0KCQl9CgkJaWYgKGFiW2tdICE9IE5BKQoJCXsKCQkJcmVjdXIgKGsgKyAxKTsKCQkJcmV0dXJuOwoJCX0KCQlkZWJ1ZyB7d3JpdGVsbiAoYWIpO30KCQlpZiAoIWNoZWNrICgpKQoJCXsKCQkJcmV0dXJuOwoJCX0KCQlmb3JlYWNoIChpOyAwLi5uKQoJCXsKCQkJaWYgKCF1W2ldKQoJCQl7CgkJCQlpZiAoaSA9PSBrIHx8IGFiW2ldICE9IE5BKQoJCQkJewoJCQkJCWNvbnRpbnVlOwoJCQkJfQoJCQkJdVtpXSA9IHRydWU7CgkJCQlhYltrXSA9IGk7CgkJCQlhYltpXSA9IGs7CgkJCQlyZWN1ciAoayArIDEpOwoJCQkJYWJbaV0gPSBOQTsKCQkJCWFiW2tdID0gTkE7CgkJCQl1W2ldID0gZmFsc2U7CgkJCX0KCQl9Cgl9CgoJcmVjdXIgKDApOwp9Cg==