From 599b1a7fcf45221bb04305b21c05fa129352cc76 Mon Sep 17 00:00:00 2001 From: Russell Champoux Date: Wed, 18 Dec 2024 22:10:13 +0000 Subject: [PATCH] day 18 pt2 --- data/examples/18.txt | 25 ++++++++ src/bin/18.rs | 138 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 data/examples/18.txt create mode 100644 src/bin/18.rs diff --git a/data/examples/18.txt b/data/examples/18.txt new file mode 100644 index 0000000..79c8583 --- /dev/null +++ b/data/examples/18.txt @@ -0,0 +1,25 @@ +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 diff --git a/src/bin/18.rs b/src/bin/18.rs new file mode 100644 index 0000000..a25e84f --- /dev/null +++ b/src/bin/18.rs @@ -0,0 +1,138 @@ +use itertools::Itertools; + +advent_of_code::solution!(18); + +const GRID_HEIGHT: usize = 71; +const GRID_WIDTH: usize = 71; + +pub fn part_one(input: &str) -> Option { + run_maze_pt1(input, GRID_HEIGHT, GRID_WIDTH, 1024) +} + +pub fn part_two(input: &str) -> Option<&str> { + run_maze_pt2(input, GRID_HEIGHT, GRID_WIDTH, 1024) +} + +fn run_maze_pt1(input: &str, grid_height: usize, grid_width: usize, sim_steps: usize) -> Option { + let mut grid = vec![vec![None; grid_height]; grid_width]; + let mut cost = vec![vec![None; grid_height]; grid_width]; + for (tick, line) in input.lines().take(sim_steps).enumerate() { + let values = line.split(",").collect_vec(); + let col_idx = values[0].parse::().unwrap(); + let row_idx = values[1].parse::().unwrap(); + + grid[row_idx][col_idx] = Some(tick); + } + solve_maze_pt1(&grid, &mut cost, 0, 0, 0); + let exit_cost = cost[grid_height-1][grid_width-1]; + + Some(exit_cost.unwrap() as u32) +} + +fn solve_maze_pt1(grid: &[Vec>], cost: &mut [Vec>], row_idx: usize, col_idx: usize, step: usize) { + cost[row_idx][col_idx] = Some(step); + + let grid_height = grid.len(); + let grid_width = grid[0].len(); + + for d in [(-1, 0), (1, 0), (0, -1), (0, 1)] { + let new_row_idx = row_idx as isize + d.0; + let new_col_idx = col_idx as isize + d.1; + let can_step = + (0..grid_height as isize).contains(&new_row_idx) && + (0..grid_width as isize).contains(&new_col_idx) && + Option::is_none(&grid[new_row_idx as usize][new_col_idx as usize]) && + ( + Option::is_none(&cost[new_row_idx as usize][new_col_idx as usize]) || + cost[new_row_idx as usize][new_col_idx as usize] > Some(step + 1) + ); + + if can_step { + solve_maze_pt1(grid, cost, new_row_idx as usize, new_col_idx as usize, step + 1); + } + }; +} + +fn run_maze_pt2(input: &str, grid_height: usize, grid_width: usize, sim_steps: usize) -> Option<&str> { + let mut grid = vec![vec![None; grid_height]; grid_width]; + let mut lines = input.lines(); + for (tick, line) in lines.by_ref().take(sim_steps).enumerate() { + let values = line.split(",").collect_vec(); + let col_idx = values[0].parse::().unwrap(); + let row_idx = values[1].parse::().unwrap(); + + grid[row_idx][col_idx] = Some(tick); + // print!("."); + } + // println!("\nDone!"); + + let mut last_path = vec![]; + + for (tick, line) in lines.by_ref().enumerate() { + let values = line.split(",").collect_vec(); + let col_idx = values[0].parse::().unwrap(); + let row_idx = values[1].parse::().unwrap(); + grid[row_idx][col_idx] = Some(tick); + + let mut cost = vec![vec![None; grid_height]; grid_width]; + + if last_path.len() == 0 || last_path.contains(&(row_idx, col_idx)) { + // println!("SOLVE! {line}"); + solve_maze_pt1(&grid, &mut cost, 0, 0, 0); + + if Option::is_none(&cost[grid_height-1][grid_width-1]) { + return Some(line); + } else { + last_path = get_last_path(&cost, grid_height, grid_width); + } + } else { + // println!("SKIP! {line}"); + } + }; + + None +} + +fn get_last_path(cost_map: &[Vec>], grid_height: usize, grid_width: usize) -> Vec<(usize, usize)> { + let mut path = vec![(grid_height - 1, grid_width - 1)]; + + let mut cur_pos = (grid_height - 1, grid_width - 1); + + // println!("{:#?}", cost_map); + while cur_pos.0 != 0 || cur_pos.1 != 0 { + let step_down = [(-1, 0), (1, 0), (0, -1), (0, 1)].iter().find_map(|d| { + let new_row = cur_pos.0 as isize + d.0; + let new_col = cur_pos.1 as isize + d.1; + if (0..grid_height as isize).contains(&new_row) && + (0..grid_width as isize).contains(&new_col) && + ( + Option::is_some(&cost_map[new_row as usize][new_col as usize]) && + cost_map[new_row as usize][new_col as usize].unwrap() == cost_map[cur_pos.0][cur_pos.1].unwrap() - 1 + ) { + Some((new_row as usize, new_col as usize)) + } else { None } + }); + path.push(step_down.unwrap()); + cur_pos = step_down.unwrap(); + } + + path +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = run_maze_pt1(&advent_of_code::template::read_file("examples", DAY), 7, 7, 12); + assert_eq!(result, Some(22)); + } + + #[test] + fn test_part_two() { + let binding = advent_of_code::template::read_file("examples", DAY); + let result = run_maze_pt2(&binding, 7, 7, 12); + assert_eq!(result, Some("6,1")); + } +}