From 1d285ee38c9f919669304e2b5b4f59853e65b5f4 Mon Sep 17 00:00:00 2001 From: Dominic Date: Wed, 6 Dec 2023 09:04:10 +0100 Subject: [PATCH 1/2] day 6 part 1 --- inputs/day6.txt | 2 ++ src/bin/day6.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 inputs/day6.txt create mode 100644 src/bin/day6.rs diff --git a/inputs/day6.txt b/inputs/day6.txt new file mode 100644 index 0000000..57f1bf3 --- /dev/null +++ b/inputs/day6.txt @@ -0,0 +1,2 @@ +Time: 42 68 69 85 +Distance: 284 1005 1122 1341 diff --git a/src/bin/day6.rs b/src/bin/day6.rs new file mode 100644 index 0000000..595e431 --- /dev/null +++ b/src/bin/day6.rs @@ -0,0 +1,64 @@ +#![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(()) +} From 146735881add3e58062989d791329985ae870f98 Mon Sep 17 00:00:00 2001 From: Dominic Date: Wed, 6 Dec 2023 09:08:39 +0100 Subject: [PATCH 2/2] day 6 part 2 --- src/bin/day6.rs | 61 ++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/bin/day6.rs b/src/bin/day6.rs index 595e431..3601de8 100644 --- a/src/bin/day6.rs +++ b/src/bin/day6.rs @@ -30,35 +30,48 @@ fn parser() -> impl Parser, Error = Simple> { .then_ignore(end()) } +fn ways2win(t: i64, d: i64) -> i64 { + // 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 { + return 0; + } + 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); + + max - min + 1 +} + fn main() -> anyhow::Result<()> { let games = read("inputs/day6.txt", parser())?; - let mut result = 1; + println!( + "{}", + games + .iter() + .map(|game| ways2win(game.time, game.distance)) + .product::() + ); + + let mut t = 0; + let mut d = 0; 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; + t = t * 10i64.pow((game.time as f64).log10().floor() as u32 + 1) + game.time; + d = d * 10i64.pow((game.distance as f64).log10().floor() as u32 + 1) + + game.distance; } - println!("{result}"); + println!("{}", ways2win(t, d)); Ok(()) }