From b3434735e6b3718e01ae1724066f3dd2285d730a Mon Sep 17 00:00:00 2001 From: Julius de Jeu Date: Sun, 12 Dec 2021 13:12:38 +0100 Subject: [PATCH] Day 12 but faster --- src/day12.rs | 122 ++++++++------------------------------------------- 1 file changed, 19 insertions(+), 103 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index a0b75aa..4526af8 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -26,98 +26,15 @@ impl Day for Day12 { } fn part1(&self) -> anyhow::Result { - fn get_all_paths(caves: &HashMap, complete_paths: &mut Vec>, current_path: &Vec, current_cave_idx: &str) { - if current_cave_idx == "end" { - complete_paths.push(current_path.clone()); - return; - } - - let current_cave = caves.get(current_cave_idx).expect("This cave does not exist!").clone(); - - for connected_cave in current_cave.connections { - let current = caves.get(&connected_cave).unwrap(); - match current.cave_type { - CaveType::Small => { - if current_path.iter().find(|&cave_pair| cave_pair == &connected_cave) != None { - continue; - } - } - _ => (), - } - - let mut new_path = current_path.clone(); - new_path.push(connected_cave.clone()); - get_all_paths(&caves, complete_paths, &new_path, &connected_cave); - } - } - - let mut complete_paths = Vec::new(); - let current_path = vec!["start".into()]; - - get_all_paths(&self.0, &mut complete_paths, ¤t_path, "start".into()); - - Ok(format!("{}", complete_paths.len())) + let m = HashMap::new(); + Ok(format!("{}", self.search("start", &m, true))) } fn part2(&self) -> anyhow::Result { - let mut small_caves_thing: HashMap, Vec> = HashMap::, Vec>::new(); - fn get_all_paths(caves: &HashMap, complete_paths: &mut Vec>, current_path: &Vec, current_cave_idx: &str, small_caves_thing: &mut HashMap, Vec>) { - if current_cave_idx == "end" { - complete_paths.push(current_path.clone()); - return; - } - - - let current_cave = caves.get(current_cave_idx).expect("This cave does not exist!").clone(); - - let small_caves = { - let e = small_caves_thing.entry(current_path.clone()).or_insert(small_caves_visited_at_least_twice(caves, current_path)); - e.clone() - }; - - for connected_cave in current_cave.connections { - if connected_cave == "start" { - continue; - } - if !small_caves.is_empty() { - let current = caves.get(&connected_cave).unwrap(); - match current.cave_type { - CaveType::Small => { - if !(small_caves.len() == 1 && small_caves[0] != connected_cave) { - continue; - } - } - _ => (), - } - } - - let mut new_path = current_path.clone(); - new_path.push(connected_cave.clone()); - get_all_paths(&caves, complete_paths, &new_path, &connected_cave, small_caves_thing); - } - } - - let mut complete_paths = Vec::new(); - let current_path = vec!["start".into()]; - - get_all_paths(&self.0, &mut complete_paths, ¤t_path, "start", &mut small_caves_thing); - - Ok(format!("{}", complete_paths.len())) + let m = HashMap::new(); + Ok(format!("{}", self.search("start", &m, false))) } } - -fn small_caves_visited_at_least_twice(caves: &HashMap, current_path: &Vec) -> Vec { - let mut small_cave_indices = HashMap::new(); - for cave_name in current_path { - let c = caves.get(cave_name).expect("how?"); - if c.cave_type == CaveType::Small { - let e = small_cave_indices.entry(cave_name).or_insert(0); - *e += 1; - } - } - return small_cave_indices.iter().filter(|(_, &b)| b > 1).map(|(&a, _)| a.clone()).collect(); -} - #[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone)] enum CaveType { Large, @@ -153,23 +70,22 @@ impl Cave { impl Day12 { fn search(&self, cur: &str, had: &HashMap, part1: bool) -> i32 { let mut had = had.clone(); - if had.values().any(|&i| i > 0) || part1 { + if had.values().any(|&i| i > 1) || part1 { if had.contains_key(cur) { return 0; } } - if cur == "start" && had.contains_key("start") { return 0; } if cur == "end" { return 1; } - if cur.chars().all(|x| x.is_lowercase()) { + let n = self.0.get(cur).unwrap(); + if n.cave_type == CaveType::Small { let e = had.entry(cur.into()).or_insert(0); *e += 1; } - let n = self.0.get(cur).unwrap(); return n.connections.iter().map(|c| self.search(c, &mut had, part1)).sum::(); } } @@ -237,12 +153,12 @@ start-RW"; Ok(()) } - // #[test] - // fn part1_real() -> anyhow::Result<()> { - // let d = Day12::init(crate::load_input("12")?)?; - // assert_eq!("4885", d.part1()?); - // Ok(()) - // } + #[test] + fn part1_real() -> anyhow::Result<()> { + let d = Day12::init(crate::load_input("12")?)?; + assert_eq!("4885", d.part1()?); + Ok(()) + } #[test] fn part2_test_1() -> anyhow::Result<()> { @@ -259,12 +175,12 @@ start-RW"; } // These are very slow, so they are commented out. - // #[test] - // fn part2_test_3() -> anyhow::Result<()> { - // let d = Day12::init(INPUT_3.to_string())?; - // assert_eq!("3509", d.part2()?); - // Ok(()) - // } + #[test] + fn part2_test_3() -> anyhow::Result<()> { + let d = Day12::init(INPUT_3.to_string())?; + assert_eq!("3509", d.part2()?); + Ok(()) + } #[test] fn part2_real() -> anyhow::Result<()> {