Day 15 part 2
authorGrégory Burri <gregory.burri@matisa.ch>
Tue, 17 Dec 2019 09:00:24 +0000 (10:00 +0100)
committerGrégory Burri <gregory.burri@matisa.ch>
Tue, 17 Dec 2019 09:00:24 +0000 (10:00 +0100)
src/day15.rs
src/main.rs

index 5e6b653..86073b4 100644 (file)
@@ -1,6 +1,7 @@
 use super::intcode;\r
 use std::iter::FromIterator;\r
 use std::collections::HashMap;\r
+use std::collections::HashSet;\r
 \r
 #[derive(Debug, Eq, PartialEq, Copy, Clone)]\r
 enum LocationState {\r
@@ -10,10 +11,13 @@ enum LocationState {
     DeadEnd,\r
 }\r
 \r
-struct DroidTrackingSystem {\r
+#[derive(Clone)]\r
+pub struct DroidTrackingSystem {\r
     board: HashMap<(i32, i32), LocationState>,\r
     current_path: Vec<(i32, i32)>,\r
-    oxygen_found: bool\r
+    oxygen_location: (i32, i32),\r
+    steps_to_oxygen: i32,\r
+    all_locations_explored: bool,\r
 }\r
 \r
 impl DroidTrackingSystem {\r
@@ -21,7 +25,9 @@ impl DroidTrackingSystem {
         DroidTrackingSystem {\r
             board: HashMap::from_iter(vec![((0, 0), LocationState::Visited)].into_iter()),\r
             current_path: vec![(0, 0)],\r
-            oxygen_found: false\r
+            oxygen_location: (0, 0),\r
+            steps_to_oxygen: 0,\r
+            all_locations_explored: false\r
         }\r
     }\r
 \r
@@ -60,19 +66,25 @@ impl DroidTrackingSystem {
             }\r
         }\r
 \r
-        panic!("Droid stuck");\r
+        self.all_locations_explored = true;\r
+        1\r
     }\r
 \r
     // 0: droid hit a wall, 1: droid moved one step, 2: droid moved one step and has found the oxygen system.\r
     fn reply_from_droid(&mut self, status: i64) {\r
-        match status {\r
-            0 => {\r
-                self.set_state(self.current_position(), LocationState::Wall);\r
-                self.current_path.pop();\r
+        if status == 0 {\r
+            self.set_state(self.current_position(), LocationState::Wall);\r
+            self.current_path.pop();\r
+        } else if status == 1 || status == 2 {\r
+            self.set_state(self.current_position(), LocationState::Visited);\r
+\r
+            // We need to explore all positions even if we find the oxygen to compute the time (see 'time_to_flood_the_area') in part 2.\r
+            if status == 2 {\r
+                self.steps_to_oxygen = self.current_path.len() as i32 - 1;\r
+                self.oxygen_location = self.current_position();\r
             }\r
-            1 => self.set_state(self.current_position(), LocationState::Visited),\r
-            2 => self.oxygen_found = true,\r
-            _ => panic!("Unkown droid status: {}", status)\r
+        } else {\r
+            panic!("Unkown droid status: {}", status)\r
         }\r
     }\r
 }\r
@@ -89,12 +101,34 @@ impl intcode::IO for DroidTrackingSystem {
     }\r
 \r
     fn halt(&self) -> bool {\r
-        self.oxygen_found\r
+        self.all_locations_explored\r
     }\r
 }\r
 \r
-pub fn nb_of_movement_to_reach_oxygen(code: &[i64]) -> i32 {\r
+pub fn nb_of_movement_to_reach_oxygen(code: &[i64]) -> (i32, DroidTrackingSystem) {\r
     let mut dts = DroidTrackingSystem::new();\r
     intcode::execute_op_code_with_custom_io(code, &mut dts);\r
-    dts.current_path.len() as i32 - 1\r
+    (dts.steps_to_oxygen, dts)\r
+}\r
+\r
+pub fn time_to_flood_the_area(dts: &DroidTrackingSystem) -> i32 {\r
+    let mut dts = dts.clone(); // To be mutable.\r
+    dts.current_path = vec![dts.oxygen_location];\r
+    let mut visited: HashSet<(i32, i32)> = HashSet::from_iter(dts.current_path.iter().copied());\r
+    let mut max_length = 0;\r
+\r
+    'main: while !dts.current_path.is_empty() {\r
+        for (_, pos) in dts.positions_around() {\r
+            if dts.get_state(pos) != LocationState::Wall && !visited.contains(&pos) {\r
+                dts.current_path.push(pos);\r
+                visited.insert(pos);\r
+                max_length = max_length.max(dts.current_path.len() as i32);\r
+                continue 'main;\r
+            }\r
+        }\r
+\r
+        dts.current_path.pop();\r
+    }\r
+\r
+    max_length - 1\r
 }
\ No newline at end of file
index 9b2570d..491ee5c 100644 (file)
@@ -113,7 +113,8 @@ fn day14() -> String {
 
 fn day15() -> String {
     let code = common::read_list_of_numbers("data/day15.input", ",");
-    format!("part1: {}, part2: {}", day15::nb_of_movement_to_reach_oxygen(&code), "")
+    let (n, dts) = day15::nb_of_movement_to_reach_oxygen(&code);
+    format!("part1: {}, part2: {}", n, day15::time_to_flood_the_area(&dts))
 }
 
 fn format_micros(t: u128) -> String {