From: Greg Burri Date: Tue, 3 Feb 2026 20:30:13 +0000 (+0100) Subject: Day 18 X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=c5ec4ee79c76a022821f4a2d14e781eb0729ea85;p=advent_of_code_2024.git Day 18 --- diff --git a/src/day18.rs b/src/day18.rs new file mode 100644 index 0000000..a8ed7f1 --- /dev/null +++ b/src/day18.rs @@ -0,0 +1,140 @@ +use std::{ + collections::{HashMap, HashSet, VecDeque}, + io::BufRead, +}; + +type Pos = (i32, i32); + +pub struct CorruptedLocations { + positions: Vec, + x_max: i32, + y_max: i32, +} + +pub fn read_byte_positions(reader: &mut dyn BufRead) -> CorruptedLocations { + let mut positions = Vec::new(); + for l in reader.lines() { + let pos: Vec = l + .unwrap() + .split(",") + .map(|s| s.parse::().unwrap()) + .collect(); + positions.push((pos[0], pos[1])); + } + + let x_max = positions.iter().max_by(|a, b| a.0.cmp(&b.0)).unwrap().0; + let y_max = positions.iter().max_by(|a, b| a.1.cmp(&b.1)).unwrap().1; + + CorruptedLocations { + positions, + x_max, + y_max, + } +} + +fn neighbours(x: i32, y: i32) -> [Pos; 4] { + [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)] +} + +pub fn shortest_path( + corrupted_locations: &CorruptedLocations, + n_first_location: usize, +) -> Vec { + let locations: HashSet<&Pos> = + HashSet::from_iter(corrupted_locations.positions[0..n_first_location].iter()); + let mut heads = VecDeque::from([(0, 0)]); + + let mut visited: HashMap = HashMap::from([((0, 0), (0, 0))]); + + while let Some((x, y)) = heads.pop_front() { + for (xn, yn) in neighbours(x, y) { + if xn < 0 + || xn > corrupted_locations.x_max + || yn < 0 + || yn > corrupted_locations.y_max + || locations.contains(&(xn, yn)) + { + continue; + } + + if xn == corrupted_locations.x_max && yn == corrupted_locations.y_max { + let mut path = vec![(xn, yn)]; + let (mut x, mut y) = (x, y); + while x != 0 || y != 0 { + path.push((x, y)); + (x, y) = visited[&(x, y)]; + } + return path; + } + + visited.entry((xn, yn)).or_insert_with(|| { + heads.push_back((xn, yn)); + (x, y) + }); + } + } + + Vec::new() +} + +pub fn first_position_cutting_the_path( + corrupted_locations: &CorruptedLocations, + start_length: usize, +) -> Pos { + let mut path = shortest_path(corrupted_locations, start_length); + for l in start_length + 1..=corrupted_locations.positions.len() { + if path.contains(&corrupted_locations.positions[l - 1]) { + path = shortest_path(corrupted_locations, l); + // Can't find a path -> return the previous corrupted byte position. + if path.is_empty() { + return corrupted_locations.positions[l - 1]; + } + } + } + + (0, 0) +} + +#[cfg(test)] +mod tests { + use super::*; + + static BYTE_POSITIONS: &str = "5,4 +4,2 +4,5 +3,0 +2,1 +6,3 +2,4 +1,5 +0,6 +3,3 +2,6 +5,1 +1,2 +5,5 +2,5 +6,5 +1,4 +0,4 +6,4 +1,1 +6,1 +1,0 +0,5 +1,6 +2,0"; + + #[test] + fn part1() { + let positions = read_byte_positions(&mut BYTE_POSITIONS.as_bytes()); + assert_eq!(shortest_path(&positions, 12).len(), 22); + } + + #[test] + fn part2() { + let positions = read_byte_positions(&mut BYTE_POSITIONS.as_bytes()); + let pos = first_position_cutting_the_path(&positions, 12); + assert_eq!(pos, (6, 1)); + } +} diff --git a/src/days.rs b/src/days.rs index 3fc858a..4735e09 100644 --- a/src/days.rs +++ b/src/days.rs @@ -156,3 +156,10 @@ pub fn day17(reader: &mut dyn BufRead) -> String { let reg_a = day17::fix_corrupted_reg_a(&mut state, &program); format!("part1: '{output}', part2: {reg_a}") } + +pub fn day18(reader: &mut dyn BufRead) -> String { + let corrupted_locations = day18::read_byte_positions(reader); + let path = day18::shortest_path(&corrupted_locations, 1024); + let (x, y) = day18::first_position_cutting_the_path(&corrupted_locations, 1024); + format!("part1: {}, part2: {},{}", path.len(), x, y) +} diff --git a/src/main.rs b/src/main.rs index 98da7f9..8135823 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ mod day14; mod day15; mod day16; mod day17; -// mod day18; +mod day18; // mod day19; // mod day20; // mod day21; @@ -48,7 +48,7 @@ fn main() { days::day15, days::day16, days::day17, - // days::day18, + days::day18, // days::day19, // days::day20, // days::day21,