From f3304cff3fc3614a691539c3174980a02f72f19a Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 24 Dec 2023 13:53:00 +0200 Subject: Day 24 part 1 --- 2023/src/bin/day_24.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 8 deletions(-) (limited to '2023/src/bin') diff --git a/2023/src/bin/day_24.rs b/2023/src/bin/day_24.rs index b3a610b..325b4cc 100644 --- a/2023/src/bin/day_24.rs +++ b/2023/src/bin/day_24.rs @@ -1,19 +1,98 @@ -use nom::IResult; +use nalgebra::{Matrix2, Point2, Point3, Vector2, Vector3}; +use nom::{ + bytes::complete::tag, + character::complete::{i64, line_ending}, + combinator::map, + multi::separated_list1, + sequence::{separated_pair, tuple}, + IResult, +}; use std::fs; fn main() -> Result<(), Box> { - let input = fs::read_to_string("inputs/day_2.txt")?; - let parsed = Example::parser(&input).unwrap().1; - dbg!(&parsed); + let input = fs::read_to_string("inputs/day_24.txt")?; + let parsed = Hailstones::parser(&input).unwrap().1; + dbg!(&parsed.count_intersections_2d(200000000000000., 400000000000000.)); Ok(()) } #[derive(Debug)] -struct Example; +struct Hailstones(Vec); -impl Example { - fn parser(_input: &str) -> IResult<&str, Self> { - todo!() +#[derive(Debug)] +struct Hailstone { + initial_position: Point3, + velocity: Vector3, +} + +impl Hailstones { + fn parser(input: &str) -> IResult<&str, Self> { + map(separated_list1(line_ending, Hailstone::parser), Hailstones)(input) + } + + fn count_intersections_2d(&self, min: f64, max: f64) -> usize { + self.0 + .iter() + .enumerate() + .map(|(i, hailstone)| { + self.0 + .iter() + .skip(i + 1) + .filter(|other_hailstone| hailstone.intersects_2d(other_hailstone, min, max)) + .count() + }) + .sum() + } +} + +impl Hailstone { + fn parser(input: &str) -> IResult<&str, Self> { + map( + separated_pair( + map( + tuple((i64, tag(", "), i64, tag(", "), i64)), + |(x, _, y, _, z)| Point3::new(x as f64, y as f64, z as f64), + ), + tag(" @ "), + map( + tuple((i64, tag(", "), i64, tag(", "), i64)), + |(x, _, y, _, z)| Vector3::new(x as f64, y as f64, z as f64), + ), + ), + |(initial_position, velocity)| Hailstone { + initial_position, + velocity, + }, + )(input) + } + + fn intersects_2d(&self, other: &Hailstone, min: f64, max: f64) -> bool { + let variables = Matrix2::new( + self.velocity.x, + -other.velocity.x, + self.velocity.y, + -other.velocity.y, + ); + let constants = Vector2::new( + other.initial_position.x - self.initial_position.x, + other.initial_position.y - self.initial_position.y, + ); + + if let Some(variables_inverse) = variables.try_inverse() { + let intersection = variables_inverse * constants; + let self_t = intersection.x; + let other_t = intersection.y; + + let intersection = self.initial_position.xy() + self.velocity.xy() * self_t; + self_t >= 0. + && other_t >= 0. + && intersection.x >= min + && intersection.x <= max + && intersection.y >= min + && intersection.y <= max + } else { + false + } } } -- cgit v1.2.3