From 67f4cb57ed9a71b38b55c1aac38d8cca580d74e7 Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Sat, 21 Dec 2024 22:45:52 -0800 Subject: [PATCH] day20: part 2 solution (slow) --- .aoc_tiles/tiles/2024/20.png | Bin 7925 -> 9455 bytes README.md | 2 +- src/day20.rs | 86 +++++++++++++++++++++++++---------- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/.aoc_tiles/tiles/2024/20.png b/.aoc_tiles/tiles/2024/20.png index 852cf09c6fbef1cf7dfcec6b87f0f5e82e43c5a8..5d13312f54475862d3b11400c352bdb0cea751f7 100644 GIT binary patch literal 9455 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 literal 7925 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 Myt-Vaj9K{q07qAFd;kCd diff --git a/README.md b/README.md index 63f53a4..422c0bf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- 2024 - 42 ⭐ - Rust + 2024 - 43 ⭐ - Rust

diff --git a/src/day20.rs b/src/day20.rs index 514d38d..0927e46 100644 --- a/src/day20.rs +++ b/src/day20.rs @@ -1,18 +1,7 @@ -use std::{ - cmp::Reverse, - collections::{BinaryHeap, VecDeque}, -}; +use std::collections::VecDeque; use aoc_runner_derive::aoc; use grid::Grid; -use rustc_hash::{FxHashMap, FxHashSet}; - -trait PathTrack { - const DOES_WORK: bool = true; - fn new() -> Self; - fn push(&mut self, pos: (i64, i64)); - fn finalize(&mut self) {} -} struct RaceTrack { map: Grid, @@ -21,7 +10,7 @@ struct RaceTrack { #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] struct State { pos: (i64, i64), - cost: usize, + cost: u64, } #[derive(Clone, Debug, Eq, PartialEq, Hash)] @@ -50,15 +39,12 @@ impl RaceTrack { _ => None, }) } - fn path_costs(&self, start: (i64, i64), goal: (i64, i64)) -> (Vec<(i64, i64)>, Grid>) { + fn path_costs(&self, start: (i64, i64), goal: (i64, i64)) -> (Vec<(i64, i64)>, Grid>) { let mut queue = VecDeque::new(); let mut visited = self.map.same_shape(None); let start_state = CheatState { - s: State { - pos: start, - cost: 0usize, - }, + s: State { pos: start, cost: 0 }, p: Vec::new(), }; visited.set(&start, Some(0)); @@ -86,9 +72,9 @@ impl RaceTrack { fn find_cheats( &self, path: &Vec<(i64, i64)>, - costs: &Grid>, - min: usize, - ) -> Vec<((i64, i64), (i64, i64), usize)> { + costs: &Grid>, + min: u64, + ) -> Vec<((i64, i64), (i64, i64), u64)> { let mut cheats = Vec::new(); for pos in path { let local_cost = costs.get(pos).unwrap().unwrap(); @@ -107,6 +93,47 @@ impl RaceTrack { } cheats } + + fn taxi_dist(&self, from: &(i64, i64), to: &(i64, i64)) -> Option { + if self.map.is_valid(to) { + Some(from.0.abs_diff(to.0) + from.1.abs_diff(to.1)) + } else { + None + } + } + + fn find_cheats_n( + &self, + path: &Vec<(i64, i64)>, + costs: &Grid>, + max_length: u64, + min: u64, + ) -> Vec<((i64, i64), (i64, i64))> { + let mut cheats = Vec::new(); + let mut solutions = self.map.clone(); + + for pos in path { + let from_cost = costs.get(pos).unwrap().unwrap(); + for x in 0..self.map.width() as i64 { + for y in 0..self.map.height() as i64 { + if let Some(dist) = self.taxi_dist(pos, &(x, y)) { + if dist <= max_length && dist >= 2 { + if let Some(to_cost) = costs.get(&(x, y)).unwrap() { + solutions.set(pos, b'O'); + solutions.set(&(x, y), b'O'); + if *to_cost > (from_cost + dist) && (to_cost - (from_cost + dist) >= min) { + cheats.push((*pos, (x, y))); + } + } + } + } + solutions.set(&(x, y), *self.map.get(&(x, y)).unwrap()); + } + } + solutions.set(pos, *self.map.get(pos).unwrap()); + } + cheats + } } fn parse(input: &str) -> RaceTrack { @@ -114,7 +141,7 @@ fn parse(input: &str) -> RaceTrack { RaceTrack { map } } -fn part1_impl(input: &str, cheat_min: usize) -> i64 { +fn part1_impl(input: &str, cheat_min: u64) -> i64 { let track = parse(input); let start = track.map.find(&b'S').unwrap(); let goal = track.map.find(&b'E').unwrap(); @@ -124,6 +151,16 @@ fn part1_impl(input: &str, cheat_min: usize) -> i64 { cheats.len() as i64 } +fn part2_impl(input: &str, max_length: u64, cheat_min: u64) -> i64 { + let track = parse(input); + let start = track.map.find(&b'S').unwrap(); + let goal = track.map.find(&b'E').unwrap(); + let (best_path, costs) = track.path_costs(start.into(), goal.into()); + let cheats = track.find_cheats_n(&best_path, &costs, max_length, cheat_min); + + cheats.len() as i64 +} + #[aoc(day20, part1)] pub fn part1(input: &str) -> i64 { part1_impl(input, 100) @@ -131,7 +168,7 @@ pub fn part1(input: &str) -> i64 { #[aoc(day20, part2)] pub fn part2(input: &str) -> i64 { - todo!() + part2_impl(input, 20, 100) } #[cfg(test)] @@ -160,6 +197,7 @@ mod tests { #[test] fn part2_example() { - assert_eq!(part2(EXAMPLE), 0); + assert_eq!(part2_impl(EXAMPLE, 2, 0), 44); + assert_eq!(part2_impl(EXAMPLE, 20, 50), 285); } }