use std::io::{stdin, BufRead}; use anyhow::{anyhow, Result}; fn collect_list(prefix: &str, buf: &str) -> Result> { Ok(buf.strip_prefix(prefix) .ok_or(anyhow!("Incorrect line: {buf:?}"))? .split_whitespace() .map(|v| v.parse::()) .collect::>()?) } fn aggregate(nums: &[usize]) -> usize { nums.iter().fold(0, |acc, d| { acc * (10u64.pow(d.ilog10() + 1) as usize) + d } ) } fn ways((t,d) : (usize, usize)) -> usize { if t*t < 4*d { return 0; } let dq = t*t - 4*d; let delta = (dq as f64).sqrt(); let b1 = ((t as f64 - delta)/2f64).floor() as usize + 1; let b2 = ((t as f64 + delta)/2f64).ceil() as usize - 1; if b2 < b1 { return 0; } eprintln!("t={t} d={d} b1={b1} b2={b2}"); b2 - b1 + 1 } fn main() -> Result<()> { let mut stdin = stdin().lock(); let mut buf = String::with_capacity(1024); stdin.read_line(&mut buf)?; let times = collect_list("Time:", &buf)?; buf.clear(); stdin.read_line(&mut buf)?; let distances = collect_list("Distance:", &buf)?; buf.clear(); let ways1: usize = times.iter().copied() .zip(distances.iter().copied()) .map(ways) .product(); println!("Part 1: {ways1} ways."); let time2 = aggregate(×); let dist2 = aggregate(&distances); let ways2 = ways((time2, dist2)); println!("Part 2: {ways2} ways."); Ok(()) }