from fractions import Fraction as F def run(load,check): old=load('C319_DATA.json');reg=load('C286_DATA.json')['target_register'];pairs=load('C286_DATA.json')['source_pairs'];rows=[];groups=[] for x in old['rows']: i,a,b=x['i'],x['a'],x['b'];tag=f'i{i}/{a}{b}' nn=[z for z in reg if z['tradition']=='SP' and z['role']=='Noah birth' and z['Cainan']==0 and z['Terah60']==0 and z['full430']==1 and z['center']==x['n']];check(tag+' Nsource',len(nn)==1);N=nn[0];g=N['gear'];rail=N['rail'] dd=[z for z in reg if z['tradition']=='SP' and z['role']=='Noah death' and z['gear']==g and z['rail']==rail and z['Cainan']==0 and z['Terah60']==0 and z['full430']==1];mm=[z for z in reg if z['tradition']=='MT' and z['role']=='Noah birth' and z['gear']==g and z['Cainan']==1 and z['Terah60']==1 and z['full430']==1];check(tag+' D/Msource',len(dd)==len(mm)==1);D,M=dd[0],mm[0] rr=[z for z in reg if z['tradition']=='MT' and z['role']==('Flood start' if rail=='primary' else 'Flood close') and z['gear']==g+b//2 and z['Cainan']==1 and z['Terah60']==1 and z['full430']==1 and z['center']==x['R']];ss=[z for z in pairs if z['Shem_Cainan']==1 and z['Shem_index']==i+a and z['S']==x['S']] check(tag+' originaladmission',bool(rr)==x['regular_admitted'] and bool(ss)==x['cumulative_admitted'] and bool(rr and ss)==x['joint_admitted']) life=N['center']-D['center'];tail=D['center']-x['R'];res=M['center']-D['center'];part108=life==950 and tail==108;part490=res==490 check(tag+' deathformula',life==950 and tail==110-b and part108==(b==2)) check(tag+' rail490formula',res==(490 if rail=='primary' else 491) and part490==(rail=='primary')) check(tag+' restated2K',part108==(x['n']-x['R']==1058)) comps=[] for oldc in x['components']: S,q,R,n=map(F,oldc);e=n-x['n'];d=F(D['center'])+e;m=F(M['center'])+e check(tag+str(e)+' inheritedcomponents',n-d==life and d-R==tail and m-d==res and R-S==8993+b-a) comps.append({'phase':str(e),'S':str(S),'q':str(q),'R':str(R),'N':str(n),'M':str(m),'D':str(d),'death_to_R':str(d-R),'MT_Noah_to_SP_death':str(m-d)}) rows.append({'a':a,'b':b,'i':i,'rail':rail,'SP_gear':g,'N':N,'D':D,'M':M,'R_matches':rr,'S_admitted':bool(ss),'joint_admitted':x['joint_admitted'],'S':x['S'],'q':x['q'],'R':x['R'],'Noah_life':life,'death_to_R':tail,'MT_Noah_to_SP_death':res,'has950_108':part108,'has490':part490,'has_both':part108 and part490,'two17K':x['two17K'],'allK':x['allK'],'components':comps}) for a in [0,2]: for b in [0,2]: sub=[x for x in rows if x['a']==a and x['b']==b and x['joint_admitted']] groups.append({'a':a,'b':b,'admitted':len(sub),'has950_108':sum(x['has950_108'] for x in sub),'has490':sum(x['has490'] for x in sub),'has_both':sum(x['has_both'] for x in sub),'allK':sum(x['allK'] for x in sub),'both_i':[x['i'] for x in sub if x['has_both']]}) survivors=[{'a':x['a'],'b':x['b'],'i':x['i']} for x in rows if x['joint_admitted'] and x['has_both']];check('two survivingtogglechoices',set((x['a'],x['b']) for x in survivors)=={(0,2),(2,2)}) combined=[{'a':x['a'],'b':x['b'],'i':x['i']} for x in rows if x['joint_admitted'] and x['has_both'] and x['two17K']] check('combinedtwo17K conditional22',len(combined)==2 and {x['i'] for x in combined}=={3,5} and all(x['a']==x['b']==2 for x in combined)) counts={'formal_candidates':len(rows),'joint_admitted':sum(x['joint_admitted'] for x in rows),'held_phase_instances':sum(len(x['components']) for x in rows),'admitted950_108':sum(x['joint_admitted'] and x['has950_108'] for x in rows),'admitted490':sum(x['joint_admitted'] and x['has490'] for x in rows),'admitted_both':len(survivors),'admitted_allK':sum(x['joint_admitted'] and x['allK'] for x in rows)} check('counts',counts=={'formal_candidates':20,'joint_admitted':14,'held_phase_instances':40,'admitted950_108':6,'admitted490':9,'admitted_both':4,'admitted_allK':3}) return {'step':'C332','rows':rows,'groups':groups,'both_survivors':survivors,'both_plus_two17K_survivors':combined,'counts':counts,'selector_result':'950+108 restates right2K and selects b2 only;490 selects primaryrail withinheldcontexts. Both leave02 and22 at i3/5.','C287_i2_status':'Retained inC331; outsideC319controlslicei3..7, not newlyrejected.','source_selector_established':False,'new_endpoints_adopted':False}