Compare commits

..

2 commits

Author SHA1 Message Date
146735881a
day 6 part 2 2023-12-06 09:08:39 +01:00
1d285ee38c
day 6 part 1 2023-12-06 09:04:10 +01:00
2 changed files with 79 additions and 0 deletions

2
inputs/day6.txt Normal file
View file

@ -0,0 +1,2 @@
Time: 42 68 69 85
Distance: 284 1005 1122 1341

77
src/bin/day6.rs Normal file
View file

@ -0,0 +1,77 @@
#![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<char, Vec<Game>, Error = Simple<char>> {
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<String>, Vec<String>)| {
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 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())?;
println!(
"{}",
games
.iter()
.map(|game| ways2win(game.time, game.distance))
.product::<i64>()
);
let mut t = 0;
let mut d = 0;
for game in &games {
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!("{}", ways2win(t, d));
Ok(())
}