//! Exact checker for equal-bead continuous interval coloring certificates.
use std::{env,fs,process};
fn fail(s:impl AsRef<str>)->!{eprintln!("FAIL: {}",s.as_ref());process::exit(1)}
fn gcd(mut a:u128,mut b:u128)->u128{while b!=0{let r=a%b;a=b;b=r}a}
fn frac(s:&str)->(u128,u128){let mut p=s.split('/');let a=p.next().and_then(|x|x.parse().ok()).unwrap_or_else(||fail("bad fraction"));let b=p.next().and_then(|x|x.parse().ok()).unwrap_or_else(||fail("bad fraction"));if p.next().is_some()||b==0{fail("bad fraction")}(a,b)}
fn main(){let p=env::args().nth(1).unwrap_or_else(||fail("usage: check-interval-beads CERT"));if env::args().nth(2).is_some(){fail("too many args")}let s=fs::read_to_string(p).unwrap_or_else(|e|fail(format!("read: {e}")));let mut x=s.split_whitespace();if x.next()!=Some("AP_INTERVAL_BEADS_V1")||x.next()!=Some("beads"){fail("header")}let q:usize=x.next().and_then(|z|z.parse().ok()).unwrap_or_else(||fail("beads"));if q==0||q>100_000{fail("bead range")}if x.next()!=Some("colors"){fail("colors label")}let c=x.next().unwrap_or_else(||fail("colors missing")).as_bytes();if c.len()!=q||c.iter().any(|z|*z!=b'0'&&*z!=b'1'){fail("colors")}
 if x.next()!=Some("claimed_weighted_mono"){fail("score label")}let claim:u128=x.next().and_then(|z|z.parse().ok()).unwrap_or_else(||fail("score"));if x.next()!=Some("claimed_continuous"){fail("continuous label")}let fc=frac(x.next().unwrap_or(""));if x.next()!=Some("claimed_delta"){fail("delta label")}let fd=frac(x.next().unwrap_or(""));if x.next().is_some(){fail("trailing tokens")}
 let mut score=0u128;for i in 0..q{for j in 0..q{let sum=i+j;if sum%2==0{let h=sum/2;if c[i]==c[j]&&c[j]==c[h]{score+=2}}else{let h=sum/2;for m in [h,h+1]{if c[i]==c[j]&&c[j]==c[m]{score+=1}}}}}if score!=claim{fail(format!("score {score} != {claim}"))}let den_c=2*(q as u128)*(q as u128);let g=gcd(score,den_c);if fc!=(score/g,den_c/g){fail("continuous fraction")}let den_d=8*(q as u128)*(q as u128);let g=gcd(score,den_d);if fd!=(score/g,den_d/g){fail("delta fraction")}
 println!("PASS: weighted monochromatic score {score}");println!("PASS: continuous monochromatic fraction {}/{}",fc.0,fc.1);println!("PASS: delta_3 <= {}/{}",fd.0,fd.1)
}
