My attempts to solve puzzles of Advent of Code
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(perf): day 12

+330 -2
+23
Cargo.lock
··· 6 6 name = "aoc-2022" 7 7 version = "0.1.0" 8 8 dependencies = [ 9 + "indexmap", 9 10 "nom", 11 + ] 12 + 13 + [[package]] 14 + name = "autocfg" 15 + version = "1.1.0" 16 + source = "registry+https://github.com/rust-lang/crates.io-index" 17 + checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 18 + 19 + [[package]] 20 + name = "hashbrown" 21 + version = "0.12.3" 22 + source = "registry+https://github.com/rust-lang/crates.io-index" 23 + checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 24 + 25 + [[package]] 26 + name = "indexmap" 27 + version = "1.9.2" 28 + source = "registry+https://github.com/rust-lang/crates.io-index" 29 + checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 30 + dependencies = [ 31 + "autocfg", 32 + "hashbrown", 10 33 ] 11 34 12 35 [[package]]
+1
Cargo.toml
··· 11 11 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 12 13 13 [dependencies] 14 + indexmap = "1.9.2" 14 15 nom = "7"
+41
data/day12.txt
··· 1 + abaaaaaccccccccaaaaaaaaaaccccaaaaaaaaaccccaacccccccccccccccccccccaaaaaaaaaaaccaaaaaaaaaccccccccccaaaaaaaacaaaaaaccccccccccccccccccccccccccccccccccccccccccaaaaa 2 + abaaaaaaaccccccaaaaaaaaaacccccaaaaaacccccaaaacccccccccccccaacccccaaaaaaaaaaaacaaaaaaaaacccccccccaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccccccccaaaa 3 + abacaaaaaccccccccaaaaaacccccccaaaaaacccccaaaacccccccccccccaacccaaaaaaaaaaaaaacaaaaaaaaccccccccccaaaaaaaaaaaaaaaaccccccccccccccccccccccccccaaaccccccccccccccaaaa 4 + abccaacccccccccccaaaaaaccccccaaaaaaacccccaaaacccaacccccaaaaaaaaaaaaaaaaaaaaacaaaaaaaccccccccccccacaaaaaccaaaaaaaccccccccccccccccccccccccccaaccccccccccccccaaaaa 5 + abcaaccccccccaaaaaaaaaaccccccaaacaaaccccccccccccaaaaaccaaaaaaaaaaaaaaaaaaaaaccaccaaacccccccccccccccaaaacccaaaaaaccccccccccccccccccccccccccaaacccccccccccccaaaca 6 + abcccccccccccaaaaaaaaaaaaacccccccccacccccccccccaaaaacccccaaaacaaaaaaaaaaaaccccaaaaaaccccccccaaacccccaaccccaacccccccccccccccccccccccaaaaccaaaccccccccccccccccccc 7 + abccccccccccaaaaaaccccaaaacccccccccccccccccccccaaaaaaccccaaaaaaaaaaaaaacaaacccaaaaaaaacccccaaaaaacccccccccccccccccccccccccccccccccccaaaaaaaaacccccccccccccccccc 8 + abacccccccccaaaaaacccccaaacaaacccccccccacccaaccccaaaacccaaacaaaaaaaaaaacccccccaaaaaaaacccccaaaaaaccccccccccccccccccccccccccccccccjjjjjjjaaaaaaaaaccccaacccccccc 9 + abaccccccccccaaaaaccaaaaaaaaaaccaccccccaacaaacccaaccccccaacccaaaaaaaaaaacccccccaaaaaaacccccaaaaaccccccccccccccccccccccccccccccccijjjjjjjjjhhhhhhhhhcaaaaaaccccc 10 + abaacccccccccaaaccccaaaaaaaaaaaaaccccccaaaaacccccccccccccccccccccaaaaaaacccccccaaaaaccccccccaaaaacccccccccccccccaaaaccccccccccciijjjjjjjjjhhhhhhhhhhcaaaaaccccc 11 + abaaccccccccccccccccccaaaaaacaaaaaacccccaaaaaacccccccccccaaacccccaaaccccccccccaaaaaaccccccccaacaacccccccccccccccaaaaccccccccccciiioooooojjhhhhpphhhhhaaaaaccccc 12 + abacccccccccccccccccccaaaaaaccaaaaacccaaaaaaaacccccccccccaaaaaaccaacccccccccccccccaaccccccccacccccccccccccccccccaaaaccccccccccciiioooooooooopppppphiiaaaaaacccc 13 + abaccccccccccaaaaaccccaaaaaaaaaaaaccccaaaaaaaacccccccccaaaaaaaaccccccccccccaaaaccccccccccccaaacccccccccccccccccccaaccccccccccciiinnoouuooooopppppppiiaaaaaacccc 14 + abcccccccccccaaaaaccccaaacaaaaccaacccccccaaccccccccccccaaaaaaaaccccccccccccaaaaccccccccaaacaaacccccccccccccccccccccccccccccccciiinnotuuuuoopuuuupppiiaaacaccccc 15 + abccccccccccaaaaaaccccaccccccccccccccccccaaccccccccccccaaaaaaacccccccaaacccaaaaccccccccaaaaaaaaaacccaacccccccccccccccccccccccciiinntttuuuuuuuuuuuppiiiaaccccccc 16 + abaaccccccccaaaaaaccccccccccccccccccaaaacccccccccccccccccaaaaaacccccaaaaccccaaccccccccccaaaaaaaaacccaaacaaacaaaccccccccccaaccciiinntttxxuuuuuuuuuppiiiccccccccc 17 + abaacccccccccaaaaaccccccccccccccccccaaaaccccccccaccccccccaaaaaacccccaaaaccccccccccccccccccaaaaacccccaaaaaaacaaaacccccccccaaaaiiiinnttxxxxuuyyyuvvppiiiccccccccc 18 + abaacccccccccaaaccccccccccccccccccccaaaaccaaacaaaacccccccaaccccccccccaaacccccccccccccccccaaaaaaccccccaaaaaacaaaacccccccccaaaaiiinnnttxxxxxxyyyvvppqiiiccccccccc 19 + abaccccccccccccccccccccaaccccccccccccaacccaaaaaaaacccccccccccccccccccccccccccccccccccaacaaaaaaacccaaaaaaaaccaaaccccccccaaaaahhhinnntttxxxxxyyyvvqqqiiiccccccccc 20 + abcccccccccccccccccccaaaaaaccccccccccccccccaaaaaaaaaccccccccccccccccccccccccccccccaaaaaaaaacaaacccaaaaaaaaaccccccccccccaaaaahhhnnnttttxxxxyyyvvvqqqiiiccccccccc 21 + SbcccccccccccccccccccaaaaaaccccccccccccccccaaaaaaaaaccccccccccccccccccccccccccccccaaaaacccccccacccaaaaaaaaaacccccccccccccaahhhnnntttxxxEzzzyyyvvvqqqjjjcccccccc 22 + abcccccccccccccccccccaaaaacccccccccccccaaaaaaaaaaaacccccccccccccccccccccccccccccccaaaaaaaccccccccccccaaacaaacccccccccccccahhhmmmtttxxxxxyyyyyyyvvvqqqjjjccccccc 23 + abccccccccccccccccccccaaaaacccccccccaacaaaaaaaaaaaaccccaccaaaccccccccccccccccccccaaaaaaaaccccccccccccaaacccccccccccccaaccahhhmmmtttxxxyywyyyyyyvvvqqqjjjccccccc 24 + abccccccccccccccccccccaaaaacccccccccaaaaaaaacaaacccccccaaaaaaccccaccaaaccccccccccaaaaaaaaccccccccccccaacccccccccccccaaaccchhhmmmsssxxwwwyyywyyvvvvqqqjjjccccccc 25 + abccaacccccccccccccccccccccccccccccccaaaaaaccaaacccccccaaaaaaccccaacaaacccccccccccacaaacccccccccccccccccccccccccaaaaaaaccchhhmmmssssswwwwyywwvvvvvqqqjjjdcccccc 26 + abccaaaccaaccccccccccccccccccccccccaaaaaaaaccaaccccccccaaaaaaacccaaaaaccccccccccccccaaacccccccccccccccccccccccccaaaaaaaaaahhhmmmmsssssswwywwwrvvqqqqqjjjdddcccc 27 + abccaaaaaaacccccaaaccccccccccccccccaaaaacaacccccccccccaaaaaaaaccccaaaaaaccccccccaaaccccccccccccccccccccccccccccccaaaaaaaaahhhgmmmmmsssswwwwwrrrrrqqqjjjjdddcccc 28 + abcccaaaaaacccccaaacacccccccccccccccccaaaccaacccccccccaaaaaaaaccaaaaaaaacaaccccaaaacccccccccccccccccccccccccccccccaaaaaaaccggggmmmmmmssswwwwrrrrrkjjjjjddddcccc 29 + abaaaaaaaaccccaacaaaaaccccaaacccccccccaaaccaaccccccccccccaaaccccaaaaacaaaaaccccaaaacccccccccccaacccccccccccaaccccaaaaaacccccgggggmmmllssswwrrrkkkkkjjjddddacccc 30 + abaaaaaaaaacccaaaaaaaaccccaaaacccccccccaaaaaaccccccccccccaaacccccccaacccaaacaaacaaaccccccccccaaaacccccccaaaaaacccaaaaaaacccccgggggglllsssrrrrrkkkkkkdddddaacccc 31 + abaaaaaaaaaacccaaaaaccccccaaaaccccccccccaaaaaaaccccccaaccccccccccccaaaaaaaaaaaaccccccccccccccaaaacccccccaaaaaccccaaccaaacccccccggggglllsrrrrrkkkeeedddddaaccccc 32 + abaacaaaaaaaccccaaaaacccccaaaccccccccccccaaaaaaccccaaaaccccccccccccccaaaaaaaaacccccccccccccccaaaacccccccaaaaaaacccccccaacccccccccgggglllrrrrkkkeeeeeddaaaaccccc 33 + abaaaaaacccccccaaacaacccccccccccccccccccaaaaaccccccaaaaaaccccccccaaacccaaaaacccccccccccccccccccccccccccaaaaaaaacccccccccccccccccccggfllllllkkkeeeeeccaaaaaacccc 34 + abaaaaacccccccccaacccccccccccccccccccccaaaaaacccccccaaaacccccacccaaccccaaaaaaccccccccccccccccccccccccccaaaaaaaacccccccccccaacccccccffflllllkkkeeeccccaaaaaacccc 35 + abaaaaacccccccccccccccccccccccccccaacccccccaaccccccaaaaacccccaaaaaaaccaaaaaaaaaaccccccccccccccccccccccccacaaacccccccccaaccaaccccccccfffllllkeeeecccccaacccccccc 36 + abaaaacccccccccccccccccccccccccccaaacccccccccccccccaacaacccccaaaaaaccaaaaacaaaaaccccccccccccccccccccccccccaaacccccccccaaaaaaccccccccffffffffeeeeccccccccccccccc 37 + abaaaccccccccccccccccccccccccccccaaaaacacccccccccccccccccccccaaaaaaaaaaaaccaaaaaaaaccccccaaccccccccccaaaaacccccccccccccaaaaaaacccccccfffffffeeaaccccccccccccaaa 38 + abaacccccaacaacccccccccccccaacaaaaaaaaaacccccccaaccccccccccccaaaaaaaaaaacccaaaaaaaacccccaaacaacccccccaaaaaccccccccccaaccaaaaaaccccccccafffffeaacccccccccccccaaa 39 + abaaaccccaaaaacccccccccccccaacaaaaaaaaaaccccccaaaccccccccccccaaaaaaaaaaaccccaaaaaccccccccaaaaaccccccaaaaaacccccccaacaaaaaaaaccccccccccaaacccccccccccccccccccaaa 40 + abccccccccaaaaacccccccccaaaaaaaaaaaaaacccccaaaaacaaccccccaaaaaaaaaaaaaaaaaaaaaaaaacccccaaaaaacccccccaaaaaacccccccaaaaaaaacaaccccccccccaaaccccccccccccccccaaaaaa 41 + abcccccccaaaaaacccccccccaaaaaaaaaaaaaacccccaaaaaaaaccccccaaaaacaaaaaaaaaaaaaaaaaaacccccaaaaaaaacccccaaaaaaccccccaaaaaaaaccaacccccccccccccccccccccccccccccaaaaaa
+4 -2
src/main.rs
··· 1 - use crate::solutions::year_2022::{Day2, Day3, Day4, Day5, Day6, Day7, Day8, Day9, Day10, Day11}; 1 + use crate::solutions::year_2022::{ 2 + Day10, Day11, Day12, Day2, Day3, Day4, Day5, Day6, Day7, Day8, Day9, 3 + }; 2 4 use aoc_lib::Solver; 3 5 pub mod solutions; 4 6 5 7 fn main() { 6 - let sol = Day11::solve_part2(); 8 + let sol = Day12::solve_part2(); 7 9 println!("{:?}", sol); 8 10 }
+259
src/solutions/year_2022/day12.rs
··· 1 + use std::{collections::BinaryHeap, fmt::Debug, hash::Hash, iter::repeat_with}; 2 + 3 + use aoc_lib::{Input, Solver}; 4 + use indexmap::{ 5 + map::Entry::{Occupied, Vacant}, 6 + IndexMap, 7 + }; 8 + 9 + pub struct Day12 { 10 + grid: Vec<Vec<Pos>>, 11 + start: Pos, 12 + goal: Pos, 13 + } 14 + 15 + impl Solver for Day12 { 16 + fn day() -> u8 { 17 + 12 18 + } 19 + type OutputPart1 = usize; 20 + type OutputPart2 = usize; 21 + fn solution_part1(input: aoc_lib::Input) -> Option<Self::OutputPart1> { 22 + let d = Day12::setup(input); 23 + let ret = shortest_path(&d.start, |p| d.successors(p, false), |g| d.reached_end(g)); 24 + ret.map(|(xs, _)| xs.len() - 1) 25 + } 26 + fn solution_part2(input: aoc_lib::Input) -> Option<Self::OutputPart2> { 27 + let d = Day12::setup(input); 28 + let ret = shortest_path(&d.goal, |p| d.successors(p, true), |s| d.reached_a(s)); 29 + ret.map(|(xs, _)| xs.len() - 1) 30 + } 31 + } 32 + 33 + impl Day12 { 34 + fn setup(input: Input) -> Self { 35 + let mut start = None; 36 + let mut goal = None; 37 + let grid = input 38 + .lines 39 + .iter() 40 + .enumerate() 41 + .map(|(row, line)| { 42 + line.chars() 43 + .enumerate() 44 + .map(|(col, c)| { 45 + if c == 'S' { 46 + let pos = Pos(row as i32, col as i32, 'a'); 47 + start = Some(pos); 48 + pos 49 + } else if c == 'E' { 50 + let pos = Pos(row as i32, col as i32, 'z'); 51 + goal = Some(pos); 52 + pos 53 + } else { 54 + Pos(row as i32, col as i32, c) 55 + } 56 + }) 57 + .collect::<Vec<_>>() 58 + }) 59 + .collect::<Vec<Vec<_>>>(); 60 + Day12 { 61 + grid, 62 + start: start.unwrap(), 63 + goal: goal.unwrap(), 64 + } 65 + } 66 + 67 + fn index(&self, x: &i32, y: &i32, compare: &char, desc: bool) -> Option<Pos> { 68 + self.grid 69 + .get(*x as usize) 70 + .and_then(|r| r.get(*y as usize)) 71 + .and_then(|c| { 72 + if (desc && (c.2 as u32) + 1 >= (*compare) as u32) 73 + || (!desc && (c.2 as u32) <= ((*compare) as u32) + 1) 74 + { 75 + Some(Pos(*x, *y, c.2)) 76 + } else { 77 + None 78 + } 79 + }) 80 + } 81 + 82 + fn successors(&self, Pos(x, y, c): &Pos, desc: bool) -> Vec<(Pos, usize)> { 83 + vec![(-1, 0), (1, 0), (0, -1), (0, 1)] 84 + .iter() 85 + .map(|(dx, dy)| self.index(&(x + dx), &(y + dy), c, desc)) 86 + .into_iter() 87 + .filter(|p| p.is_some()) 88 + .map(|p| (p.unwrap(), 1)) 89 + .collect() 90 + } 91 + 92 + fn reached_end(&self, p: &Pos) -> bool { 93 + p == &self.goal 94 + } 95 + 96 + fn reached_a(&self, p: &Pos) -> bool { 97 + p.2 == 'a' 98 + } 99 + } 100 + 101 + fn reverse_paths<Node: Eq + Hash + Clone + Copy, F>( 102 + prevs: &mut IndexMap<Node, (VisitedIndex, Weight)>, 103 + mut prev: F, 104 + start: usize, 105 + ) -> Vec<Node> 106 + where 107 + F: FnMut(&(VisitedIndex, Weight)) -> usize, 108 + { 109 + let mut i = start; 110 + let xs = repeat_with(|| { 111 + let ps = prevs.clone(); 112 + ps.get_index(i) 113 + .map(|(n, t)| { 114 + i = prev(t); 115 + n 116 + }) 117 + .copied() 118 + }) 119 + .take_while(|x| x.is_some()) 120 + .flatten(); 121 + 122 + let mut y = xs.collect::<Vec<_>>(); 123 + y.reverse(); 124 + y 125 + } 126 + 127 + fn shortest_path<Node, FN, IN, FS>( 128 + start_node: &Node, 129 + mut next_nodes: FN, 130 + mut stop_check: FS, 131 + ) -> Option<(Vec<Node>, Weight)> 132 + where 133 + Node: Eq + Hash + Clone + Debug + Copy, 134 + FN: FnMut(&Node) -> IN, 135 + IN: IntoIterator<Item = (Node, Weight)> + Debug, 136 + FS: FnMut(&Node) -> bool, 137 + { 138 + let mut q: BinaryHeap<State> = BinaryHeap::new(); 139 + let mut prev: IndexMap<Node, (VisitedIndex, Weight)> = IndexMap::new(); 140 + 141 + // initiate queue 142 + q.push(State::default()); 143 + // initiate prev 144 + prev.insert(*start_node, (usize::MAX, 0)); 145 + 146 + let mut destination_index: Option<usize> = None; 147 + while let Some(State { weight, index }) = q.pop() { 148 + let (node, (_, w)) = prev.get_index(index).unwrap(); 149 + // check if we need to stop 150 + if stop_check(node) { 151 + destination_index = Some(index); 152 + break; 153 + } 154 + 155 + // if we have already seen the node and the last path to it was best then 156 + // don't bother, continue 157 + if weight > *w { 158 + continue; 159 + } 160 + 161 + // at this point we need to look at the successors 162 + let next_nodes = next_nodes(node); 163 + 164 + for (next_node, travel_weight) in next_nodes { 165 + let new_weight = weight + travel_weight; 166 + let i; 167 + match prev.entry(next_node) { 168 + Occupied(visited) => { 169 + let visited_weight = visited.get().1; 170 + if visited_weight > new_weight { 171 + i = visited.index(); 172 + prev.insert(next_node, (index, new_weight)); 173 + } else { 174 + continue; 175 + } 176 + } 177 + Vacant(unvisited) => { 178 + i = unvisited.index(); 179 + prev.insert(next_node, (index, new_weight)); 180 + } 181 + } 182 + 183 + q.push(State { 184 + index: i, 185 + weight: new_weight, 186 + }); 187 + } 188 + } 189 + 190 + destination_index.map(|target| { 191 + ( 192 + reverse_paths(&mut prev, |&(p, _)| p, target), 193 + prev.get_index(target).unwrap().1 .1, 194 + ) 195 + }) 196 + } 197 + 198 + type VisitedIndex = usize; 199 + type Weight = usize; 200 + 201 + #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] 202 + struct Pos(i32, i32, char); 203 + 204 + #[derive(Debug, Default)] 205 + struct State { 206 + weight: Weight, 207 + index: VisitedIndex, 208 + } 209 + 210 + impl PartialEq for State { 211 + fn eq(&self, other: &Self) -> bool { 212 + self.weight == other.weight 213 + } 214 + } 215 + impl Eq for State {} 216 + 217 + impl Ord for State { 218 + fn cmp(&self, other: &Self) -> std::cmp::Ordering { 219 + other 220 + .weight 221 + .cmp(&self.weight) // this is key for Min-Priority heap 222 + .then_with(|| self.index.cmp(&other.index)) // when tied, compare the indexes 223 + } 224 + } 225 + 226 + impl PartialOrd for State { 227 + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { 228 + Some(self.cmp(other)) 229 + } 230 + } 231 + 232 + #[cfg(test)] 233 + mod tests { 234 + use super::*; 235 + 236 + #[test] 237 + fn test1() { 238 + static GOAL: (i32, i32) = (4, 6); 239 + let result = shortest_path( 240 + &(1, 1), 241 + |&(x, y)| { 242 + vec![ 243 + (x + 1, y + 2), 244 + (x + 1, y - 2), 245 + (x - 1, y + 2), 246 + (x - 1, y - 2), 247 + (x + 2, y + 1), 248 + (x + 2, y - 1), 249 + (x - 2, y + 1), 250 + (x - 2, y - 1), 251 + ] 252 + .into_iter() 253 + .map(|p| (p, 1)) 254 + }, 255 + |&p| p == GOAL, 256 + ); 257 + assert_eq!(result.expect("no path found").1, 4); 258 + } 259 + }
+2
src/solutions/year_2022/mod.rs
··· 9 9 mod day9; 10 10 mod day10; 11 11 mod day11; 12 + mod day12; 12 13 pub(crate) use day1::*; 13 14 pub(crate) use day2::*; 14 15 pub(crate) use day3::*; ··· 20 21 pub(crate) use day9::*; 21 22 pub(crate) use day10::*; 22 23 pub(crate) use day11::*; 24 + pub(crate) use day12::*;