this repo has no description
1use std::fs;
2use std::collections::HashMap;
3
4fn main() {
5 let raw_contents = fs::read_to_string("input.txt").expect("File not found");
6 let contents = raw_contents.trim(); // remove trailing \n
7
8 let orbits = input_to_orbits(contents);
9
10 // Part 1. Count the distance to COM for each individual planet.
11 let num_orbits = orbits.keys().clone().fold(0, |sum, planet| {
12 sum + count_to_center(orbits.clone(), *planet, 0)
13 });
14 println!("Part 1: {}", num_orbits);
15
16 // Part 2. Count distance until common orbital ancestor.
17 let dist_from_san = count_to_destination(orbits.clone(), vec!["YOU"], vec!["SAN"]);
18 println!("Part 2: {}", dist_from_san);
19}
20
21fn input_to_orbits(input: &str) -> HashMap<&str, &str> {
22 input.split('\n').fold(HashMap::new(), |mut m, line| {
23 let pair = line.split(')').into_iter();
24 m.insert(pair.clone().nth(1).unwrap(), pair.clone().nth(0).unwrap()); m
25 })
26}
27
28fn count_to_center(orbits: HashMap<&str, &str>, planet: &str, sum: usize) -> usize {
29 match orbits.get(planet) {
30 Some(&"COM") => sum + 1,
31 Some(p) => count_to_center(orbits.clone(), p, sum + 1),
32 None => unreachable!(),
33 }
34}
35
36fn count_to_destination(orbits: HashMap<&str, &str>, from: Vec<&str>, to: Vec<&str>) -> usize {
37 let f = from.iter().last().unwrap();
38 let t = to.iter().last().unwrap();
39
40 let f_next = orbits.get(f).unwrap_or(&f);
41 let t_next = orbits.get(t).unwrap_or(&t);
42
43 match (from.iter().position(|x| x == t_next), to.iter().position(|x| x == f_next)) {
44 (Some(_), Some(_)) => from.len() + to.len() - 2,
45 (Some(i), None) => i + to.len() - 2,
46 (None, Some(i)) => from.len() + i - 2,
47 (None, None) => count_to_destination(
48 orbits.clone(),
49 [from.clone(), vec![f_next]].concat(),
50 [to.clone(), vec![t_next]].concat()
51 ),
52 }
53}