//! Day 6: Wait For It use std::ops::RangeInclusive; use itertools::Itertools; pub const DAY: u8 = 6; pub const TITLE: &str = "Wait For It"; #[derive(Debug)] struct Race { t: u64, d: u64, } impl Race { fn win_range(&self) -> RangeInclusive { let t_r = self.t as f64; let d = self.d as f64; let discriminant = (t_r.powi(2) - (4.0 * d)).sqrt(); let a = (-t_r + discriminant) / -2.0; let b = (-t_r - discriminant) / -2.0; let min = a.min(b); let max = a.max(b); let mut l = min.ceil(); if l == min { l += 1.0; } let mut h = max.floor(); if h == max { h -= 1.0 } l as u64..=h as u64 } } pub fn part1(input: Vec) -> String { let races = input[0] .split_ascii_whitespace() .skip(1) .zip(input[1].split_ascii_whitespace().skip(1)) .map(|(a, b)| Race { t: a.parse().unwrap(), d: b.parse().unwrap(), }) .collect_vec(); races .iter() .map(|r| r.win_range().try_len().unwrap()) .product::() .to_string() } pub fn part2(input: Vec) -> String { let (_, l1) = input[0].split_once(' ').unwrap(); let (_, l2) = input[1].split_once(' ').unwrap(); let t = l1.replace(' ', "").parse::().unwrap(); let d = l2.replace(' ', "").parse::().unwrap(); let race = Race { t, d }; race.win_range().try_len().unwrap().to_string() } #[cfg(test)] mod tests { use super::*; #[test] fn t_example1() { assert_eq!(part1(crate::read_example(DAY, 1)), "288"); } #[test] fn t_part1() { assert_eq!(part1(crate::read_input(DAY)), "505494"); } #[test] fn t_example2() { assert_eq!(part2(crate::read_example(DAY, 2)), "71503"); } #[test] fn t_part2() { assert_eq!(part2(crate::read_input(DAY)), "23632299"); } }