diff --git a/inputs/day12.txt b/inputs/day12.txt new file mode 100644 index 0000000..7c5a212 --- /dev/null +++ b/inputs/day12.txt @@ -0,0 +1,41 @@ +abaaacccccccccaaaaaaccccccccccccccccaacccccccccccaacaaaaaaaaaaaaaaaaaccaaaaacccaaaaccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaa +abaaacccccccccaaaaaacccccccccccccccaaaaccccccccccaaaaaaaacaaaaaaaaaaaccaaaaaaccaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaa +abaaaccccccccccaaaaacccccccccccccccaaaacccccccccccaaaaacccaaaaaaaaaacccaaaaaacccaaccccccccccccccaaaaacccccccccccccccccccccccccccccccccccccaaaaaa +abccccaaccccccaaaaacccccccccaaaaaccaaaaccccccccccccaaaaacaaaaaaaaacccccaaaaaccccccccccccccccccccaaaaacccccccccccccccccaaaccccaaaccccccccccaaacaa +abcccaaaacccccaaaaacccccccccaaaaacccccccccccccccccaaacaaaaaaaaaacccccccaaaaacccccccccccccccccccaaaaaacccccccccccccccccaaaaccaaaaccccccccccccccaa +abcccaaaaacacccccccccccccccaaaaaaccccccccccccccccccaaccaaaaacaaaaccccccccccccccccccccccccccccccaaaaaaccccccccccccccccccaaaaaaaacccccccccccccccaa +abaaaaaaaaaacccccccccccccccaaaaaaccccccccccccccccccccccaaaacccaaaccccccccccccccccccccccccccccccaaaaaacccccccccccccccciiiiijaaaaccccccccccccccccc +abaaaaaaaaaacccccccccccccccaaaaaacccccccccccccccccccccccccccccaaacccccccccccccccccccccccccccccccaaaccccccccccccccccciiiiiijjjaccccccccaaaccccccc +abccaaaaaaccccccccccccccccccaaaccccccccccccccccccccccccccccccccacccccccccccaacccccccccccccccccccccccccccccccccccccciiiiioijjjjaaccccccaaaaaacccc +abccaaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccccccccciiinnooojjjjjaaccaaaaaaaacccc +abccaaaaaacccccccccccccccccccccccccccccccccccccaacccccaacccccccccccccccccaaaaaacccccccccccccccccccccccccccaaaccccciiinnnoooojjjjjjkkkaaaaaaacccc +abcaaaaaaaaccccccccccccccccccccccccccccccccccccaaaccaaaaaaccccaaacccccccccaaaacccccccccccccccccccccccccccccaaaaccciiinnnouooojjjjkkkkkaaaaaccccc +abccaccccccccccccccccccaaccccccaccccccccccccaaaaaaaaaaaaaacccaaaacccccccccaaaacccccccccccccccccccccccccccaaaaaacchhinnnttuuooooookkkkkkkaaaccccc +abccccccccccccccccccaacaaaccccaaaaaaaaccccccaaaaaaaacaaaaacccaaaacccccccccaccacccccccccccccccccccccccccccaaaaacchhhhnntttuuuooooppppkkkkcaaacccc +abccccccccaaacccccccaaaaaccccccaaaaaaccccccccaaaaaacaaaaaccccaaaaccccccccccccccccccccccccccccaccccccccccccaaaaahhhhnnntttxuuuooppppppkkkcccccccc +abccccccccaaaacccccccaaaaaaccccaaaaaaccaaacccaaaaaacaaaaaccccccccccccccaaccccccccccccccaaaaaaaacccccccccccaachhhhhnnnntttxxuuuuuuuupppkkkccccccc +abccccccccaaaacccccaaaaaaaacccaaaaaaaacaaacacaaaaaaccccccccccccccccccccaacccccccccccccccaaaaaacccccccccccccchhhhmnnnntttxxxxuuuuuuupppkkcccccccc +abacccccccaaaacccccaaaaacaaccaaaaaaaaaaaaaaaaaaccaacccccccccccccccccaaaaaaaaccccccccccccaaaaaaccccccccccccchhhhmmmntttttxxxxuyyyuvvpppklcccccccc +abacccccccccccccccccacaaaccaaaaaaaaaaaaaaaaaaaccccccccccccccccccccccaaaaaaaacccccccccccaaaaaaaaccccccccccccgghmmmtttttxxxxxxyyyyvvvpplllcccccccc +abaccccccccaacccccccccaaaccaaaaaaaacaaaaaaaaaaccccccccccccccccccccccccaaaaccccccccccccaaaaaaaaaaccccccaccccgggmmmtttxxxxxxxyyyyyvvppplllcccccccc +SbaaaccccccaaacaaaccccccccaaaaaaaaacaaaaaaaaacccccccccccccccccccccccccaaaaacccccccccccaaaaaaaaaaaaacaaaccaagggmmmtttxxxEzzzzyyyvvppplllccccccccc +abaacccccccaaaaaaacccccccaaaaaaacaaccaaaaaaaccccccccccccccaaaccccccccaaaaaacccccccccccacacaaacccaaaaaaacaaagggmmmsssxxxxxyyyyyvvvqqqlllccccccccc +abaccccccccaaaaaaccacccaaaaaaaaacccccccaaaaaaccccccccccccaaaaccccccccaaccaacccccccccccccccaaaccccaaaaaaccaagggmmmssssxxwwyyyyyyvvqqqlllccccccccc +abaccccccaaaaaaaaccaacaaaccaaaaaacccccaaaaaaaccccccccccccaaaaccccccccccaacccccccccccccccccaacccccaaaaaaaaaaggggmmmssssswwyywyyyyvvqqlllccccccccc +abaccccccaaaaaaaaacaaaaacccaaaaaacccccaaacaaaccccccccccccaaaaccccccccaaaaaaccccccccccccaacccccccaaaaaaaaaaaaggggmmmossswwyywwyyvvvqqqllccccccccc +abcccccccaaaaaaaaaacaaaaaacaaccccccccaaacccccccccccccccccccccccccccccaaaaaaccccccccccccaaaaacccaaaaaaaaaaaaaaggggoooosswwywwwwvvvvqqqmlccccccccc +abccccccccccaaacaaaaaaaaaacccccccccccaaacaccccccccccccccccccccccccccccaaaaccccccccccccaaaaaccccaaacaaacccaaacagggfooosswwwwwrvvvvqqqqmmccccccccc +abccccccccccaaacccaaaaaaaacccccccccaacaaaaacccccccccccccccccccccccccccaaaaccccccccccccaaaaaacccccccaaacccaaccccfffooosswwwwrrrrrqqqqqmmccccccccc +abccccccccccaacccccccaaccccccccccccaaaaaaaacccccccccccccaaccccccccccccaccaccccccccccccccaaaacccccccaacccccccccccfffoossrwrrrrrrrqqqqmmmccccccccc +abccaaaccccccccccccccaacccccccccccccaaaaaccccccccccccaacaacccccccaaaaacccccccccccccccccaacccccccccccccccccccccccfffoossrrrrrnnnmqqmmmmmccccccccc +abcaaaaccccccccccccccccccccccccccccccaaaaacccccccccccaaaaacccccccaaaaacccaaaccccccccccccccccccccccccccccccccccccfffooorrrrrnnnnmmmmmmmccccaacccc +abcaaaacccccccccccccccccccccccccccccaaacaaccccacccccccaaaaaaccccaaaaaaccccaaaccacccccccccccccccccccccccccccccccccffoooonnnnnnnnmmmmmmccccaaacccc +abccaaacccccccccccccccccccccaaaaaccccaaccccaaaacccccaaaaaaaaccccaaaaaaccccaaaaaaaccccccccccccccccaccaccccccccccccfffooonnnnnnddddddddcccaaaccccc +abccccccccccccccccccccccccccaaaaaccccccccccaaaaaacccaaaaacaacccaaaaaaaccaaaaaaaacccccccccccccccccaaaaccccccccccccfffeonnnnneddddddddddcaaacccccc +abccccccccccaaaccccccccccccaaaaaacccccccccccaaaacccccacaaacccccaacaacccaaaaaaaaacccccccccccccccccaaaacccccccccccccffeeeeeeeeddddddddcccaaacccccc +abcccccccccaaaaccccacccccccaaaaaaccccccccccaaaaacccccccaaaacccaaacaccccaaaaaaaaaccccccccccccccccaaaaaaccccccccccccceeeeeeeeedacccccccccccccccccc +abaccccccccaaaaccccaaacaaacaaaaaaccccccccccaacaaccccccccaaaacaaaacaaacaaaaaaaaaacccccccccccccaacaaaaaacccccccccccccceeeeeeeaaacccccccccccccccaaa +abaaacccccccaaaccccaaaaaaaccaaaccccccccaaacccccccccccccccaaaaaaaacaaaaaaaaaaaaaaacacaaccaaacaaacccaacccccccccccccccccaacccaaaacccccccccccccccaaa +abaaaccccccccccccccaaaaaaccccccccccccccaaacccccccccccccccaaaaaaaccaaaaaaccaacccaccaaaaccaaaaaaaccccccccaaccccccccccccccccccaaacccccccccccccccaaa +abaaccccccccccccccaaaaaaacccccccccccaaaaaaaaccccccccccccccaaaaaaaaaaaaaacaaaccccccaaaaaccaaaaaaccccccaaaaccccccccccccccccccaaaccccccccccccaaaaaa +abaaaccccccccccccaaaaaaaaaacccccccccaaaaaaaacccccccccccaaaaaaaaaaaaaaaaaaacccccccaaaaaacaaaaaaaaaccccaaaaaacccccccccccccccccccccccccccccccaaaaaa diff --git a/src/bin/day12_1.rs b/src/bin/day12_1.rs new file mode 100644 index 0000000..33bf86a --- /dev/null +++ b/src/bin/day12_1.rs @@ -0,0 +1,8 @@ +use std::fs; + +use aoc2022::day12::process_part_1; + +fn main() { + let file = fs::read_to_string("./inputs/day12.txt").unwrap(); + println!("{}", process_part_1(&file)); +} diff --git a/src/bin/day12_2.rs b/src/bin/day12_2.rs new file mode 100644 index 0000000..f9c980d --- /dev/null +++ b/src/bin/day12_2.rs @@ -0,0 +1,8 @@ +use std::fs; + +use aoc2022::day12::process_part_2; + +fn main() { + let file = fs::read_to_string("./inputs/day12.txt").unwrap(); + println!("{}", process_part_2(&file)); +} diff --git a/src/day12.rs b/src/day12.rs new file mode 100644 index 0000000..9da2545 --- /dev/null +++ b/src/day12.rs @@ -0,0 +1,118 @@ +use std::collections::{HashSet, VecDeque}; + +type Coord = (usize, usize); +type Map = Vec>; + +// ah yes, Breadth First Search +pub fn process_part_1(input: &str) -> u32 { + let (start, target, map) = parse_input(input); + let mut queue = VecDeque::from([(start, map[start.1][start.0], 0)]); + let mut visited = HashSet::from([start]); + + while !queue.is_empty() { + let (pos, elevation, steps) = queue.pop_front().unwrap(); + if pos == target { + return steps; + } + + for (neighbor, neighbor_elevation) in neighbors(&map, pos) { + if neighbor_elevation - elevation <= 1 && !visited.contains(&neighbor) { + queue.push_back((neighbor, neighbor_elevation, steps + 1)); + visited.insert(neighbor); + } + } + } + + panic!("no path"); +} + +pub fn process_part_2(input: &str) -> u32 { + let (_, target, map) = parse_input(input); + let mut queue = VecDeque::from([(target, map[target.1][target.0], 0)]); + let mut visited = HashSet::from([target]); + + while !queue.is_empty() { + let (pos, elevation, steps) = queue.pop_front().unwrap(); + if elevation == 0 { + return steps; + } + + for (neighbor, neighbor_elevation) in neighbors(&map, pos) { + if elevation - neighbor_elevation <= 1 && !visited.contains(&neighbor) { + queue.push_back((neighbor, neighbor_elevation, steps + 1)); + visited.insert(neighbor); + } + } + } + + panic!("no path"); +} + +pub fn parse_input(input: &str) -> (Coord, Coord, Map) { + let mut start = (0, 0); + let mut end = (0, 0); + let map = input + .lines() + .enumerate() + .map(|(y, line)| { + line.chars() + .enumerate() + .map(|(x, c)| match c { + 'S' => { + start = (x, y); + 'a' + } + 'E' => { + end = (x, y); + 'z' + } + _ => c, + }) + .map(char_to_int) + .collect() + }) + .collect(); + (start, end, map) +} + +// data only contains a-z, S and E +// this one only deals with a-z +pub fn char_to_int(c: char) -> i8 { + (c as i16 - 'a' as i16) as i8 +} + +pub fn neighbors(map: &Map, pos: Coord) -> Vec<(Coord, i8)> { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .into_iter() + .flat_map(|(x, y)| { + // Haha wow, I simultaneously hate and love this + // Reminder to the reader that flat_map flattens Options as much as it can flatten Vec's + Some(( + (pos.0.checked_add_signed(x)?), + (pos.1.checked_add_signed(y)?), + )) + }) + .flat_map(|(x, y)| Some(((x, y), *map.get(y)?.get(x)?))) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + const INPUT: &str = "Sabqponm +abcryxxl +accszExk +acctuvwj +abdefghi"; + + #[test] + fn day1() { + assert_eq!(process_part_1(INPUT), 31); + } + + #[test] + fn day2() { + assert_eq!(process_part_2(INPUT), 29); + } +} diff --git a/src/lib.rs b/src/lib.rs index a75caf3..7007440 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,3 +12,4 @@ pub mod day08; pub mod day09; pub mod day10; pub mod day11; +pub mod day12;