#![forbid(elided_lifetimes_in_paths, unsafe_code)] use aoc23::read; use chumsky::{prelude::*, text::int}; struct Game { time: i64, distance: i64 } fn parser() -> impl Parser, Error = Simple> { let int_list = just(" ") .repeated() .ignore_then(int(10).separated_by(just(" ").repeated().at_least(1))); just("Time:") .ignore_then(int_list) .then_ignore(just("\nDistance:")) .then(int_list) .map(|(times, dists): (Vec, Vec)| { times .into_iter() .zip(dists) .map(|(time, distance)| Game { time: time.parse().unwrap(), distance: distance.parse().unwrap() }) .collect() }) .then_ignore(just("\n")) .then_ignore(end()) } fn main() -> anyhow::Result<()> { let games = read("inputs/day6.txt", parser())?; let mut result = 1; for game in &games { let t = game.time; let d = game.distance + 1; // we want the minimum a s.t. (t-a)*a > d, // and the maximum a s.t. (t-a)*a < d // that means we have a quadratic function -a² + ta - d and we want to find // its intersections with the axis let discriminant = t * t - 4 * d; if discriminant < 0 { continue; } let sqrt = (discriminant as f64).sqrt(); let min = ((t as f64 - sqrt) / 2.0).ceil() as i64; let max = ((t as f64 + sqrt) / 2.0).floor() as i64; eprintln!( "t={t}, d={d}, min={min} ({}), max={max} ({})", (t - min) * min, (t - max) * max ); assert!(max >= min); result *= max - min + 1; } println!("{result}"); Ok(()) }