From 3ec90894bdf0d715a0c94b610abaa60b85d90c69 Mon Sep 17 00:00:00 2001 From: Himangshu Saikia Date: Fri, 20 Dec 2024 19:53:11 +0100 Subject: [PATCH] 2024_20 --- src/bin/2024_20/main.rs | 80 +++++++++++++++++++++++++++++++++++++++++ src/grid.rs | 16 +++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/bin/2024_20/main.rs diff --git a/src/bin/2024_20/main.rs b/src/bin/2024_20/main.rs new file mode 100644 index 0000000..1c18d9f --- /dev/null +++ b/src/bin/2024_20/main.rs @@ -0,0 +1,80 @@ +use std::collections::VecDeque; + +use aoc::{common, grid::Grid}; + +fn shortest_path(map: &Grid) -> Vec<(usize, usize)> { + let ans = Vec::new(); + let pos = map.positions('S')[0]; + let mut q = VecDeque::new(); + q.push_back(vec![pos]); + let mut visited = Vec::new(); + + while let Some(tp) = q.pop_front() { + let lst = tp.last().unwrap(); + if visited.contains(lst) { + continue; + } + visited.push(*lst); + + if map.get(lst) == 'E' { + return tp; + } + + let nx: Vec<(usize, usize)> = map + .adjacent_4(lst) + .into_iter() + .filter(|x| map.get(x) == '.' || map.get(x) == 'E') + .collect(); + + for n in nx.iter() { + let mut tp_tmp = tp.clone(); + tp_tmp.push(*n); + q.push_back(tp_tmp); + } + } + ans +} + +fn solve(input: &str) -> usize { + let map = Grid::from_str(input, |c| c); + let path = shortest_path(&map); + let path_d: Vec<((usize, usize), usize)> = + path.iter().enumerate().map(|(i, v)| (*v, i)).collect(); + + let mut res: [usize; 10000] = [0; 10000]; + + for (v1, l1) in path_d.iter() { + for (v2, l2) in path_d.iter().skip(PICOSECONDS) { + let dist = map.l1_distance(v1, v2); + if dist <= CHEAT_PICOSECONDS && *l2 > *l1 + dist { + let l = *l2 - *l1 - dist; + res[l] += 1; + } + } + } + + res.iter() + .enumerate() + .filter(|(k, _)| *k >= PICOSECONDS) + .map(|(_, v)| v) + .sum() +} + +fn main() { + let input = common::get_input(); + println!("{input:?}"); + common::timed(&input, solve::<100, 2>, true); + common::timed(&input, solve::<100, 20>, false); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_samples() { + let sample_input = "###############\n#...#...#.....#\n#.#.#.#.#.###.#\n#S#...#.#.#...#\n#######.#.#.###\n#######.#.#...#\n#######.#.###.#\n###..E#...#...#\n###.#######.###\n#...###...#...#\n#.#####.#.###.#\n#.#...#.#.#...#\n#.#.#.#.#.#.###\n#...#...#...###\n###############"; + assert_eq!(solve::<2, 2>(sample_input), 44); + assert_eq!(solve::<2, 20>(sample_input), 3081); + } +} diff --git a/src/grid.rs b/src/grid.rs index 5a77b4d..cc9748c 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -233,6 +233,22 @@ impl Grid { ret } + pub fn l1_distance(&self, idx1: &CellIndex, idx2: &CellIndex) -> usize { + let dx = if idx1.0 > idx2.0 { + idx1.0 - idx2.0 + } else { + idx2.0 - idx1.0 + }; + + let dy = if idx1.1 > idx2.1 { + idx1.1 - idx2.1 + } else { + idx2.1 - idx1.1 + }; + + dx + dy + } + pub fn adjacent_2_row(&self, idx: &CellIndex) -> Vec<(usize, usize)> { self.adjacent_in_dir(idx, &[(0, 1), (0, -1)]) }