diff --git a/src/tasks/day06.rs b/src/tasks/day06.rs index 9ea3831..d01bd8a 100644 --- a/src/tasks/day06.rs +++ b/src/tasks/day06.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::collections::VecDeque; pub fn run() { @@ -10,6 +11,7 @@ pub fn run() { }) .collect(); task1(&orbits); + task2(&orbits); } fn task1(orbit_list: &Vec<(&str, &str)>) { @@ -28,5 +30,57 @@ fn task1(orbit_list: &Vec<(&str, &str)>) { }) .sum(); println!("Task 1: there are {} direct and indirect orbits", sum); - //405096 too high +} + +fn task2(orbit_list: &Vec<(&str, &str)>) { + let mut queue = VecDeque::new(); + queue.push_back("COM"); // com is where everything floats around + let parents: HashMap<_, _> = (0..) + .scan((orbit_list, queue), |(all, queue), _| { + if let Some(next) = queue.pop_front() { + let children = all + .iter() + .filter(|(a, _)| *a == next) + .map(|(_, b)| *b) + .collect::>(); + children.iter().for_each(|b| queue.push_back(b)); + Some( + children + .into_iter() + .map(|child| (child, next)) + .collect::>(), + ) + } else { + None + } + }) + .flatten() + .collect(); + // graph maps from the name of an object A to all objects that either orbit + // A or that A directly orbits + let ancestors = |start: &str| { + let mut result = std::iter::successors(Some(start.to_string()), |last| { + parents.get(&last.as_ref()).map(|l| l.to_string()) + }) + .collect::>(); + result.reverse(); + result + }; + let a_san = ancestors("SAN"); + let a_you = ancestors("YOU"); + + let last_common_ancestor = a_san + .iter() + .zip(a_you.iter()) + .take_while(|(a, b)| a == b) + .map(|(a, _)| a) + .last() + .unwrap(); + let dist_to_ancestor = |ancestors: &Vec, target: &String| { + ancestors.iter().rev().position(|x| x == target).unwrap() + }; + let result = dist_to_ancestor(&a_san, &last_common_ancestor) - 1 + + dist_to_ancestor(&a_you, &last_common_ancestor) + - 1; // two times -1 because we search for the path length for yours and santas orbit-center + println!("Task 2: distance is {}", result); } diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index d68ddd7..cec71f7 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -1,5 +1,4 @@ pub mod day01; pub mod day03; pub mod day04; -pub mod day05; pub mod day06;