Day 6
authorUmmon <greg.burri@gmail.com>
Sun, 8 Dec 2019 18:59:49 +0000 (19:59 +0100)
committerUmmon <greg.burri@gmail.com>
Sun, 8 Dec 2019 18:59:49 +0000 (19:59 +0100)
src/day06.rs [new file with mode: 0644]
src/main.rs

diff --git a/src/day06.rs b/src/day06.rs
new file mode 100644 (file)
index 0000000..1923336
--- /dev/null
@@ -0,0 +1,88 @@
+use std::collections::HashMap;
+use std::cmp;
+
+// All planets indexing their parent (planet -> parent).
+type Orbits = HashMap<String, String>;
+
+pub fn build_orbits(orbits_str: &[&str]) -> Orbits {
+    let mut orbits = Orbits::new();
+    for orbit in orbits_str {
+        let planets: Vec<&str> = orbit.trim().split(')').collect();
+        orbits.insert(String::from(planets[1]), String::from(planets[0]));
+    }
+    orbits
+}
+
+fn parents<'a>(orbits: &'a Orbits, planet: &str) -> Vec<&'a str> {
+    let mut parents = Vec::<&str>::new();
+    let mut current_planet = planet;
+
+    loop {
+        match orbits.get(current_planet) {
+            Some (parent) => { parents.insert(0, parent); current_planet = parent; },
+            None => break
+        }
+    }
+
+    parents
+}
+
+pub fn total_direct_and_indirect_orbits(orbits: &Orbits) -> usize {
+    orbits.keys().fold(0, |sum, planet| { sum + parents(orbits, &planet).len() })
+}
+
+pub fn nb_orbital_transfers(orbits: &Orbits, loc1: &str, loc2: &str) -> usize {
+    let parents_loc1 = parents(orbits, loc1);
+    let parents_loc2 = parents(orbits, loc2);
+    for i in 0..cmp::min(parents_loc1.len(), parents_loc2.len()) {
+        if parents_loc1[i] != parents_loc2[i] {
+            return parents_loc1.len() + parents_loc2.len() - 2 * i
+        }
+    }
+    0
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn part1() {
+        let lines: Vec<&str> =
+            "COM)B
+                B)C
+                C)D
+                D)E
+                E)F
+                B)G
+                G)H
+                D)I
+                E)J
+                J)K
+                K)L".lines().collect();
+
+        let n = total_direct_and_indirect_orbits(&build_orbits(&lines));
+        assert_eq!(n, 42);
+    }
+
+    #[test]
+    fn part2() {
+        let lines: Vec<&str> =
+            "COM)B
+                B)C
+                C)D
+                D)E
+                E)F
+                B)G
+                G)H
+                D)I
+                E)J
+                J)K
+                K)L
+                K)YOU
+                I)SAN".lines().collect();
+
+        let n = nb_orbital_transfers(&build_orbits(&lines), "SAN", "YOU");
+        assert_eq!(n, 4);
+    }
+}
\ No newline at end of file
index 56fefeb..1c320c5 100644 (file)
@@ -5,6 +5,7 @@ use std::time::Instant;
 mod day01;
 mod day02;
 mod day03;
+mod day06;
 mod common;
 
 fn day01() -> String {
@@ -27,6 +28,13 @@ fn day03() -> String {
     )
 }
 
+fn day06() -> String {
+    let file_content = fs::read_to_string("data/day06.input").unwrap();
+    let lines: Vec<&str> = file_content.lines().collect();
+    let orbits = day06::build_orbits(&lines);
+    format!("part1: {}, part2: {}", day06::total_direct_and_indirect_orbits(&orbits), day06::nb_orbital_transfers(&orbits, "SAN", "YOU"))
+}
+
 fn format_micros(t: u128) -> String {
     if t < 10_000 {
         format!("{} μs", t)
@@ -48,7 +56,8 @@ fn main() {
     let days: Vec<fn() -> String> = vec!(
         day01,
         day02,
-        day03
+        day03,
+        day06
     );
 
     let args: Vec<String> = env::args().skip(1).collect();