From: Greg Burri Date: Sat, 14 Dec 2024 21:26:35 +0000 (+0100) Subject: Day 14 X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=2edbc4ef72542fb429e418adcfc27e08a4a41d04;p=advent_of_code_2024.git Day 14 --- diff --git a/src/day13.rs b/src/day13.rs index 7de4a3f..e84087d 100644 --- a/src/day13.rs +++ b/src/day13.rs @@ -16,20 +16,20 @@ pub fn read(reader: &mut dyn BufRead) -> Equations { if let Some(Ok(line1)) = iter.next() { let a_cap = button_a.captures(&line1).unwrap(); let a_factors = Vector2::new( - a_cap.get(1).unwrap().as_str().parse::().unwrap(), - a_cap.get(2).unwrap().as_str().parse::().unwrap(), + a_cap[1].parse::().unwrap(), + a_cap[2].parse::().unwrap(), ); let line2 = iter.next().unwrap().unwrap(); let b_cap = button_b.captures(&line2).unwrap(); let b_factors = Vector2::new( - b_cap.get(1).unwrap().as_str().parse::().unwrap(), - b_cap.get(2).unwrap().as_str().parse::().unwrap(), + b_cap[1].parse::().unwrap(), + b_cap[2].parse::().unwrap(), ); let line3 = iter.next().unwrap().unwrap(); let prize_cap = prize.captures(&line3).unwrap(); let prize_xy = Vector2::new( - prize_cap.get(1).unwrap().as_str().parse::().unwrap(), - prize_cap.get(2).unwrap().as_str().parse::().unwrap(), + prize_cap[1].parse::().unwrap(), + prize_cap[2].parse::().unwrap(), ); let _ = iter.next(); equations.push((a_factors, b_factors, prize_xy)); diff --git a/src/day14.rs b/src/day14.rs new file mode 100644 index 0000000..5d422ba --- /dev/null +++ b/src/day14.rs @@ -0,0 +1,114 @@ +use std::io::BufRead; + +use nalgebra::{DMatrix, Point2, Vector2}; +use regex::Regex; + +type Position = Point2; +type Velocity = Vector2; + +pub fn read(reader: &mut dyn BufRead) -> Vec<(Position, Velocity)> { + let regex_line = { Regex::new(r#"([+-]?\d+),([+-]?\d+).*?([+-]?\d+),([+-]?\d+)"#).unwrap() }; + + reader + .lines() + .map(|l| { + let l = l.unwrap(); + let captures = regex_line.captures(&l).unwrap(); + ( + Position::new( + captures[1].parse::().unwrap(), + captures[2].parse::().unwrap(), + ), + Velocity::new( + captures[3].parse::().unwrap(), + captures[4].parse::().unwrap(), + ), + ) + }) + .collect() +} + +fn robot_positions<'a>( + robots: &'a [(Position, Velocity)], + area_size: (i64, i64), + seconds: i64, +) -> impl Iterator + use<'a> { + robots.into_iter().map(move |(pos, vel)| { + let pos = pos + vel * seconds; + ( + pos[0].rem_euclid(area_size.0), + pos[1].rem_euclid(area_size.1), + ) + }) +} + +pub fn safety_factor(robots: &[(Position, Velocity)], area_size: (i64, i64), seconds: i64) -> u32 { + let quadrants = robot_positions(robots, area_size, seconds).fold( + (0, 0, 0, 0), + |(q1, q2, q3, q4), (x, y)| { + if x > area_size.0 / 2 { + if y < area_size.1 / 2 { + return (q1 + 1, q2, q3, q4); + } else if y > area_size.1 / 2 { + return (q1, q2, q3, q4 + 1); + } + } else if x < area_size.0 / 2 { + if y < area_size.1 / 2 { + return (q1, q2 + 1, q3, q4); + } else if y > area_size.1 / 2 { + return (q1, q2, q3 + 1, q4); + } + } + (q1, q2, q3, q4) + }, + ); + quadrants.0 * quadrants.1 * quadrants.2 * quadrants.3 +} + +pub fn format_robots( + robots: &[(Position, Velocity)], + area_size: (i64, i64), + seconds: i64, +) -> String { + let mut area = DMatrix::::repeat(area_size.1 as usize, area_size.0 as usize, 0); + for (x, y) in robot_positions(robots, area_size, seconds) { + area[(y as usize, x as usize)] += 1; + } + let mut str = String::new(); + for i in 0..area.nrows() { + for j in 0..area.ncols() { + let n = area[(i, j)]; + if n > 0 { + str.push('#'); + } else { + str.push(' '); + } + } + str.push('\n'); + } + str +} + +#[cfg(test)] +mod test { + use super::*; + + static POSITIONS_AND_VELOCITIES: &str = "p=0,4 v=3,-3 +p=6,3 v=-1,-3 +p=10,3 v=-1,2 +p=2,0 v=2,-1 +p=0,0 v=1,3 +p=3,0 v=-2,-2 +p=7,6 v=-1,-3 +p=3,0 v=-1,-2 +p=9,3 v=2,3 +p=7,3 v=-1,2 +p=2,4 v=2,-3 +p=9,5 v=-3,-3"; + + #[test] + fn part1() { + let robots = read(&mut POSITIONS_AND_VELOCITIES.as_bytes()); + assert_eq!(safety_factor(&robots, (11, 7), 100), 12); + } +} diff --git a/src/days.rs b/src/days.rs index 0ff4d85..2932a11 100644 --- a/src/days.rs +++ b/src/days.rs @@ -123,3 +123,14 @@ pub fn day13(reader: &mut dyn BufRead) -> String { day13::nb_tokens(&day13::add_10000000000000_to_xy(equations)) ) } + +pub fn day14(reader: &mut dyn BufRead) -> String { + let robots = day14::read(reader); + format!( + "part1: {}, part2: {}", + day14::safety_factor(&robots, (101, 103), 100), + // Found by displaying each robot positions where seconds = i * 100 + 46 + i + // and i in 0..100. + day14::format_robots(&robots, (101, 103), 7520) + ) +} diff --git a/src/main.rs b/src/main.rs index 1b92c94..e7d4c43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ mod day10; mod day11; mod day12; mod day13; -// mod day14; +mod day14; // mod day15; // mod day16; // mod day17; @@ -46,7 +46,7 @@ fn main() { days::day11, days::day12, days::day13, - // days::day14, + days::day14, // days::day15, // days::day16, // days::day17,