"""Original one-pass state and independent two-pass Fraction oracle."""
from fractions import Fraction as F
from itertools import permutations
import math,json
def validate(x):
 if type(x) not in [int,float] or abs(x)>10**13 or not math.isfinite(x):raise ValueError('bounded finite real, excluding bool')
 return x
def states(values,exact=False):
 n=0;mean=F(0) if exact else 0.0;m2=mean
 for raw in values:
  x=validate(raw);x=F(x) if exact else float(x);n+=1
  delta=x-mean;mean+=delta/n;m2+=delta*(x-mean)
  yield n,mean,m2
def oracle(vals):
 if not vals:return None
 mu=sum(map(F,vals))/len(vals);return mu,sum((F(x)-mu)**2 for x in vals)
def demo():
 data=[10**12+i for i in range(1,9)];e=list(states(iter(data),True));f=list(states(iter(data)));rows=[]
 for i,((n,mu,m2),(_,fm,fs)) in enumerate(zip(e,f),1):
  assert (mu,m2)==oracle(data[:i])
  rows.append({'n':n,'mean_exact':str(mu),'M2_exact':str(m2),'population_variance_exact':str(m2/n),'sample_variance_exact':str(m2/(n-1)) if n>1 else None,'mean_float':fm,'M2_float':fs,'float_M2_error_exact':str(F(fs)-m2)})
 assert e[-1][2]==42 and e[-1][2]/8==F(21,4) and e[-1][2]/7==6
 naive=sum(float(x)**2 for x in data)/len(data)-(sum(map(float,data))/len(data))**2
 assert list(states([],True))==[] and list(states([7],True))==[(1,F(7),F(0))]
 order_rows=[]
 for p in permutations([10**12+0.1,10**12+0.2,10**12+0.4]):
  n,mu,m2=list(states(p))[-1];target=oracle(p)[1];order_rows.append({'order':list(p),'float_M2':m2,'represented_input_exact_M2':str(target),'error_exact':str(F(m2)-target)})
 rejected=[]
 for x in [True,float('nan'),float('inf'),10**13+1]:
  try:list(states([x]))
  except ValueError:rejected.append(repr(x))
  else:raise AssertionError('expected rejection')
 reset=list(states(data[4:],True))[-1];assert reset[2]!=e[-1][2]
 return {'data':data,'prefixes':rows,'each_prefix_two_pass_exact_oracle_equal':True,'naive_float_E_x2_minus_mean2':naive,'float_order_observations_only':order_rows,'empty_state_yields':[],'singleton_sample_variance':None,'singleton_population_variance':0,'reset_second_half_only':{'n':reset[0],'mean':str(reset[1]),'M2':str(reset[2])},'online_working_state':'only n, mean, M2; traces and oracle retain data separately','rejected':rejected,'real_stream_or_model_run':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=True,indent=2))
