From 5406f765fd361b1cb2f1b089a3310f90de43855f Mon Sep 17 00:00:00 2001 From: JonOfUs Date: Mon, 12 Dec 2022 19:33:05 +0100 Subject: [PATCH] Day 12 --- res/12/input.txt | 41 +++++++++++++++ src/days/d12.rs | 130 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 6 ++- 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 res/12/input.txt create mode 100644 src/days/d12.rs diff --git a/res/12/input.txt b/res/12/input.txt new file mode 100644 index 0000000..bac8753 --- /dev/null +++ b/res/12/input.txt @@ -0,0 +1,41 @@ +abccccccccccccccccccaaaaaaaaacccccccccccccccccccccccccccccccccccccaaaa +abcccccccccccccccaaaaaaaaaaacccccccccccccccccccccccccccccccccccccaaaaa +abcaaccaacccccccccaaaaaaaaaacccccccccccccccccccccaaacccccccccccccaaaaa +abcaaaaaaccccccccaaaaaaaaaaaaacccccccccccccccccccaacccccccccccccaaaaaa +abcaaaaaacccaaacccccaaaaaaaaaaaccccccccccccccccccaaaccccccccccccccccaa +abaaaaaaacccaaaaccccaaaaaacaaaacccccccccccaaaacjjjacccccccccccccccccca +abaaaaaaaaccaaaaccccaaaaaaccccccaccccccccccaajjjjjkkcccccccccccccccccc +abaaaaaaaaccaaacccccccaaaccccccaaccccccccccajjjjjjkkkaaacccaaaccaccccc +abccaaacccccccccccccccaaccccaaaaaaaacccccccjjjjoookkkkaacccaaaaaaccccc +abcccaacccccccccccccccccccccaaaaaaaaccccccjjjjoooookkkkcccccaaaaaccccc +abcccccccaacccccccccccccccccccaaaacccccccijjjoooooookkkkccaaaaaaaccccc +abccaaccaaaccccccccccccccccccaaaaacccccciijjooouuuoppkkkkkaaaaaaaacccc +abccaaaaaaaccccccccccaaaaacccaacaaaccciiiiiooouuuuupppkkklllaaaaaacccc +abccaaaaaacccccccccccaaaaacccacccaaciiiiiiqooouuuuuupppkllllllacaccccc +abcccaaaaaaaacccccccaaaaaaccccaacaiiiiiqqqqoouuuxuuupppppplllllccccccc +abccaaaaaaaaaccaaaccaaaaaaccccaaaaiiiiqqqqqqttuxxxuuuppppppplllccccccc +abccaaaaaaaacccaaaaaaaaaaacccaaaahiiiqqqttttttuxxxxuuuvvpppplllccccccc +abcaaaaaaacccaaaaaaaaaaacccccaaaahhhqqqqtttttttxxxxuuvvvvvqqlllccccccc +abcccccaaaccaaaaaaaaaccccccccacaahhhqqqttttxxxxxxxyyyyyvvvqqlllccccccc +abcccccaaaccaaaaaaaacccccccccccaahhhqqqtttxxxxxxxyyyyyyvvqqqlllccccccc +SbcccccccccccaaaaaaaaaccccccccccchhhqqqtttxxxxEzzzyyyyvvvqqqmmlccccccc +abcccccccccccaaaaaaaacccaacccccccchhhppptttxxxxyyyyyvvvvqqqmmmcccccccc +abccccccccccaaaaaaaaaaccaacccccccchhhpppptttsxxyyyyyvvvqqqmmmccccccccc +abcaacccccccaaaaaaacaaaaaaccccccccchhhppppsswwyyyyyyyvvqqmmmmccccccccc +abaaaacccccccaccaaaccaaaaaaacccccccchhhpppsswwyywwyyyvvqqmmmddcccccccc +abaaaaccccccccccaaaccaaaaaaacccccccchhhpppsswwwwwwwwwvvqqqmmdddccccccc +abaaaacccccccccaaaccaaaaaaccccccccccgggpppsswwwwrrwwwwvrqqmmdddccccccc +abccccccaaaaaccaaaacaaaaaaccccccaacccggpppssswwsrrrwwwvrrqmmdddacccccc +abccccccaaaaaccaaaacccccaaccccaaaaaacggpppssssssrrrrrrrrrnmmdddaaccccc +abcccccaaaaaaccaaaccccccccccccaaaaaacggppossssssoorrrrrrrnnmdddacccccc +abcccccaaaaaaccccccccaaaaccccccaaaaacgggoooossoooonnnrrnnnnmddaaaacccc +abccccccaaaaaccccccccaaaacccccaaaaaccgggoooooooooonnnnnnnnndddaaaacccc +abccccccaaaccccccccccaaaacccccaaaaacccgggoooooooffennnnnnnedddaaaacccc +abcccccccccccccccccccaaacccccccaacccccggggffffffffeeeeeeeeeedaaacccccc +abccccccccccccccccccaaacccccaccaaccccccggfffffffffeeeeeeeeeecaaacccccc +abccccccccccccccccccaaaacccaaaaaaaaaccccfffffffaaaaaeeeeeecccccccccccc +abccccccccaacaaccccaaaaaacaaaaaaaaaaccccccccccaaaccaaaaccccccccccccccc +abccccccccaaaaacccaaaaaaaaaaacaaaaccccccccccccaaaccccaaccccccccccaaaca +abcccccccaaaaaccccaaaaaaaaaaacaaaaacccccccccccaaaccccccccccccccccaaaaa +abcccccccaaaaaacccaaaaaaaaaacaaaaaacccccccccccaaccccccccccccccccccaaaa +abcccccccccaaaaccaaaaaaaaaaaaaaccaaccccccccccccccccccccccccccccccaaaaa diff --git a/src/days/d12.rs b/src/days/d12.rs new file mode 100644 index 0000000..c2650f9 --- /dev/null +++ b/src/days/d12.rs @@ -0,0 +1,130 @@ +use std::{fs, collections::{HashMap, HashSet}}; + +pub fn solve() { + let path = "res/12/input.txt"; + + let contents = fs::read_to_string(path).expect("I/O error, wrong path?"); + + let lines: Vec<&str> = contents + .lines() + .collect(); + + // Build grid + let mut start = (0, 0); + let mut end = (0, 0); + let grid: Vec> = lines.iter().enumerate().map(|(y, line)| { + line.chars().enumerate().map(|(x, c)| + match c { + 'S' => { + start = (x as u32, y as u32); + return char_to_numeric('a') + + }, + 'E' => { + end = (x as u32, y as u32); + return char_to_numeric('z') + }, + _ => { + return char_to_numeric(c) + } + }).collect() + }).collect(); + + // Build adjacent lists + let mut adjacents = HashMap::<(u32,u32),Vec<(u32,u32)>>::new(); + + grid.iter() + .enumerate() + .for_each(|(y, line)| { + line.iter() + .enumerate() + .for_each(|(x, height)| { + adjacents.insert((x as u32, y as u32), Vec::<(u32,u32)>::new()); + // top + if y != 0 && grid[y-1][x] <= height+1 { + adjacents.get_mut(&(x as u32, y as u32)).unwrap().push((x as u32, (y-1) as u32)) + } + // bot + if y != grid.len()-1 && grid[y+1][x] <= height+1 { + adjacents.get_mut(&(x as u32, y as u32)).unwrap().push((x as u32, (y+1) as u32)) + } + //left + if x != 0 && grid[y][x-1] <= height+1 { + adjacents.get_mut(&(x as u32, y as u32)).unwrap().push(((x-1) as u32, y as u32)) + } + // right + if x != grid[0].len()-1 && grid[y][x+1] <= height+1 { + adjacents.get_mut(&(x as u32, y as u32)).unwrap().push(((x+1) as u32, y as u32)) + } + }) + }); + + // task 1 - find min distance between start and end + let res = bfs(start, end, &adjacents); + + println!("Result 1: {res}"); + + // task 2 - find min distance for each node with height 1, select min + let mut distances = Vec::::new(); + grid.iter() + .enumerate() + .for_each(|(y, line)| { + line.iter() + .enumerate() + .for_each(|(x, height)| { + if *height == 1 { + distances.push( + bfs((x as u32, y as u32), end, &adjacents) + ) + } + }) + }); + let res = *distances.iter() + .filter(|dist| **dist != -1) + .min() + .unwrap(); + + println!("Result 2: {res}") + +} + +// Maps lowercase chars to 1..=26 +fn char_to_numeric(c: char) -> u32 { + (c as u32) - ('a' as u32) + 1 +} + +// Runs a Breadth-first search on the given graph and returns the minimal steps necessary to reach end from start, -1 if not reachable +fn bfs(start: (u32,u32), end: (u32,u32), adjacents: &HashMap<(u32,u32),Vec<(u32,u32)>>) -> i32 { + let mut queue = Vec::<(u32,u32)>::new(); + let mut seen_nodes = HashSet::<(u32,u32)>::new(); + let mut predecessor = HashMap::<(u32,u32),(u32,u32)>::new(); + queue.push(start); + seen_nodes.insert(start); + while !queue.is_empty() { + let node = queue.remove(0); + if node == end { + break; + } + adjacents.get(&node).unwrap() + .iter() + .for_each(|child| { + if !seen_nodes.contains(child) { + queue.push(*child); + seen_nodes.insert(*child); + predecessor.insert(*child, node); + } + }) + } + // if end is reachable, it now is in predecessor + let mut res = 0; // steps + let mut node = end; + while node != start { + node = match predecessor.get(&node) { + Some(n) => *n, + None => return -1 // return -1 if end not reachable + }; + res += 1; + } + + res +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 8be9365..af085c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ pub mod days; fn main() { - days::d11::solve() + days::d12::solve() //_all_days() } @@ -26,4 +26,8 @@ fn _all_days() { days::d09::solve(); println!("\nDay 10"); days::d10::solve(); + println!("\nDay 11"); + days::d11::solve(); + println!("\nDay 12"); + days::d12::solve(); }