From 74cd67ddfc0a6a3f3d17f7b67367efcae2826ba0 Mon Sep 17 00:00:00 2001 From: Vladan Popovic Date: Sat, 28 Dec 2019 03:32:52 +0100 Subject: [PATCH] Simplified day6 :) --- src/day6.rs | 176 +++++++++++++--------------------------------------- 1 file changed, 42 insertions(+), 134 deletions(-) diff --git a/src/day6.rs b/src/day6.rs index 7f68117..30aec43 100644 --- a/src/day6.rs +++ b/src/day6.rs @@ -1,160 +1,68 @@ -use std::collections::BTreeSet; use std::collections::HashMap; +use std::iter::FromIterator; -#[derive(Debug)] -struct OrbitMap { - ids: Vec, -} - -impl OrbitMap { - fn new(n: usize) -> Self { - Self { - ids: (0..n).collect::>(), - } - } - - fn orbit_around(&mut self, base: usize, orbiter: usize) { - self.ids[orbiter] = base; - //println!("{:?}", self.ids); - } - - fn range(&self, idx: usize) -> usize { - let mut i = idx; - let mut cnt = 0; - while i != self.ids[i] { - cnt += 1; - i = self.ids[i]; - } - cnt - } - - fn range_to(&self, idx: usize, limit: usize) -> usize { - let mut i = idx; - let mut cnt = 0; - while i != limit { - i = self.ids[i]; - cnt += 1; - } - cnt - 1 - } - - fn path(&self, idx: usize) -> BTreeSet { - let mut i = idx; - let mut res = BTreeSet::new(); - while i != self.ids[i] { - res.insert(i); - i = self.ids[i]; - } - res - } - - fn distance(&self, p: usize, q: usize) -> usize { - let ppath = self.path(p); - let qpath = self.path(q); - let common_roots = ppath.intersection(&qpath); - - common_roots - .map(|cr| self.range_to(p, *cr) + self.range_to(q, *cr)) - .min() - .unwrap() - } -} - -fn get_pairs(input: &str) -> Vec> { +fn create_orbit_map(input: &str) -> HashMap { + let mut orbit_map: HashMap = HashMap::new(); input .lines() - .map(|line| line.split(")").map(String::from).collect::>()) - .collect() + .map(|line| line.split(")").map(String::from).collect()) + .for_each(|pair: Vec| { + orbit_map.entry(pair[1].clone()).or_insert(pair[0].clone()); + }); + orbit_map } -fn get_space_objects(input: &str) -> HashMap { - let items = input - .lines() - .map(|line| line.split(")").map(String::from).collect::>()) - .flatten(); +fn part1(input: &str) -> usize { + let orbit_map = create_orbit_map(input); - let mut space_objects: HashMap = HashMap::new(); - let mut n = 0; - items.for_each(|x| { - if !space_objects.contains_key(&x) { - space_objects.insert(x, n); - n += 1; + let mut cnt: usize = 0; + for obj in orbit_map.keys() { + let mut key = obj; + while let Some(val) = orbit_map.get(key) { + cnt += 1; + key = val; } - }); - //println!("{:?}", space_objects); - - space_objects + } + cnt } -fn calculate_map(input: &str) -> usize { - let space_objects = get_space_objects(input); - let pairs = get_pairs(input); - let mut orbit_map = OrbitMap::new(space_objects.len()); +fn part2(input: &str) -> usize { + let orbit_map = create_orbit_map(input); - for pair in pairs { - //println!("{:?}", pair); - let base = space_objects.get(&pair[0]).unwrap(); - let orbiter = space_objects.get(&pair[1]).unwrap(); - orbit_map.orbit_around(*base, *orbiter); + let my_traj: HashMap = HashMap::from_iter( + std::iter::successors(orbit_map.get("YOU").map(|el| (el, 0)), |(nxt, n)| { + (orbit_map.get(*nxt).map(|el| (el, n + 1 as usize))) + }) + .map(|(el, n)| (String::from(el), n)), + ); + + let mut santa_transfers = 0; + let mut santa = orbit_map.get("SAN").unwrap(); + loop { + if my_traj.contains_key(santa) { + return my_traj.get(santa).unwrap() + santa_transfers; + } else { + santa = orbit_map.get(santa).expect("no common orbits found"); + santa_transfers += 1; + } } - //println!("{:?}", orbit_map.ids); - (0..orbit_map.ids.len()).map(|i| orbit_map.range(i)).sum() -} - -fn calculate_distance(input: &str) -> usize { - let space_objects = get_space_objects(input); - let pairs = get_pairs(input); - let mut orbit_map = OrbitMap::new(space_objects.len()); - - for pair in pairs { - //println!("{:?}", pair); - let base = space_objects.get(&pair[0]).unwrap(); - let orbiter = space_objects.get(&pair[1]).unwrap(); - orbit_map.orbit_around(*base, *orbiter); - } - //println!("{:?}", orbit_map.ids); - let me = *space_objects.get("YOU").unwrap(); - let santa = *space_objects.get("SAN").unwrap(); - orbit_map.distance(me, santa) } pub fn main() -> std::io::Result<()> { let input = std::include_str!("../day6-input.txt").trim(); - println!("part1 = {:?}", calculate_map(input)); - println!("part2 = {:?}", calculate_distance(input)); + println!("part1 = {:?}", part1(input)); + println!("part2 = {:?}", part2(input)); Ok(()) } #[test] fn test_day6_part1() { - let input = "COM)B\n\ - B)C\n\ - C)D\n\ - D)E\n\ - E)F\n\ - B)G\n\ - G)H\n\ - D)I\n\ - E)J\n\ - J)K\n\ - K)L"; - assert_eq!(calculate_map(input), 42); + let input = "COM)B\nB)C\nC)D\nD)E\nE)F\nB)G\nG)H\nD)I\nE)J\nJ)K\nK)L"; + assert_eq!(part1(input), 42); } #[test] fn test_day6_part2() { - let input = "COM)B\n\ - B)C\n\ - C)D\n\ - D)E\n\ - E)F\n\ - B)G\n\ - G)H\n\ - D)I\n\ - E)J\n\ - J)K\n\ - K)L\n\ - K)YOU\n\ - I)SAN"; - assert_eq!(calculate_distance(input), 4); + let input = "COM)B\nB)C\nC)D\nD)E\nE)F\nB)G\nG)H\nD)I\nE)J\nJ)K\nK)L\nK)YOU\nI)SAN"; + assert_eq!(part2(input), 4); }