From 81bf01201ad9edc5ebfa54091146a09ea60d2fd4 Mon Sep 17 00:00:00 2001 From: mat ess Date: Mon, 12 Dec 2022 22:10:32 -0500 Subject: [PATCH] Finish day 12 --- src/main.rs | 58 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/main.rs b/src/main.rs index a2909bb..3349f53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet, VecDeque}; use std::fmt::Debug; use std::fs; use std::ops::{Range, RangeInclusive}; @@ -279,11 +279,12 @@ solutions! { // day 12 part 1 |input| { let map = Map::from_string(input); - map.navigate().into() + map.navigate(map.start).unwrap().into() }, // day 12 part 1 |input| { - todo!() + let map = Map::from_string(input); + map.best_navigate().into() }, ] } @@ -296,27 +297,40 @@ struct Map { } impl Map { - fn navigate(self) -> u64 { - // this is fuckin buggy - let (mut x, mut y) = self.start; - let mut last = (x, y); - let mut prior = (x, y); - let mut steps = 0; - while (x, y) != self.end { + fn best_navigate(self) -> u64 { + self.map + .iter() + .enumerate() + .flat_map(|(x, row)| { + row.iter() + .enumerate() + .map(move |(y, level)| (x, y, *level)) + .filter_map(|(x, y, level)| if level == 0 { Some((x, y)) } else { None }) + }) + .flat_map(|start| self.navigate(start)) + .min() + .unwrap() + } + + fn navigate(&self, start: (usize, usize)) -> Option { + let mut q = VecDeque::new(); + let mut visited = HashSet::new(); + visited.insert(start); + q.push_back((start, 0)); + while !q.is_empty() { + let ((x, y), steps) = q.pop_front().unwrap(); let level = self.map[x][y]; - print!("moving from ({x},{y}) to "); - prior = last; - last = (x, y); - (x, y, _) = self - .neighbors(x, y) - .filter(|(_, _, neighbor)| (level..=level + 1).contains(neighbor)) - .filter(|(nx, ny, _)| (*nx, *ny) != prior) - .max_by_key(|(_, _, neighbor)| *neighbor) - .unwrap(); - println!("({x},{y})"); - steps += 1; + if (x, y) == self.end { + return Some(steps); + } + for (nx, ny, nlevel) in self.neighbors(x, y) { + if !visited.contains(&(nx, ny)) && nlevel <= level + 1 { + visited.insert((nx, ny)); + q.push_back(((nx, ny), steps + 1)) + } + } } - steps + None } fn neighbors(&self, x: usize, y: usize) -> impl Iterator {