Day 15 part 1
authorUmmon <greg.burri@gmail.com>
Mon, 16 Dec 2019 22:38:26 +0000 (23:38 +0100)
committerUmmon <greg.burri@gmail.com>
Mon, 16 Dec 2019 22:38:26 +0000 (23:38 +0100)
src/day15.rs
src/intcode.rs
src/main.rs

index 8e59e65..5e6b653 100644 (file)
 use super::intcode;\r
+use std::iter::FromIterator;\r
+use std::collections::HashMap;\r
 \r
-struct RepairDroid {\r
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]\r
+enum LocationState {\r
+    Unknown,\r
+    Wall,\r
+    Visited,\r
+    DeadEnd,\r
 }\r
 \r
-impl intcode::IO for RepairDroid {\r
+struct DroidTrackingSystem {\r
+    board: HashMap<(i32, i32), LocationState>,\r
+    current_path: Vec<(i32, i32)>,\r
+    oxygen_found: bool\r
+}\r
+\r
+impl DroidTrackingSystem {\r
+    fn new() -> DroidTrackingSystem {\r
+        DroidTrackingSystem {\r
+            board: HashMap::from_iter(vec![((0, 0), LocationState::Visited)].into_iter()),\r
+            current_path: vec![(0, 0)],\r
+            oxygen_found: false\r
+        }\r
+    }\r
+\r
+    fn current_position(&self) -> (i32, i32) { *self.current_path.last().unwrap() }\r
+\r
+    fn positions_around(&self) -> Vec<(i64, (i32, i32))> {\r
+        let (x, y) = self.current_position();\r
+        vec![(1, (x, y + 1)), (2, (x, y - 1)), (3, (x - 1, y)), (4, (x + 1, y))]\r
+    }\r
+\r
+    fn get_state(&self, position: (i32, i32)) -> LocationState {\r
+        match self.board.get(&position) {\r
+            Some(state) => *state,\r
+            None => LocationState::Unknown\r
+        }\r
+    }\r
+\r
+    fn set_state(&mut self, position: (i32, i32), state: LocationState) {\r
+        self.board.insert(position, state);\r
+    }\r
+\r
+    // 1: north, 2: south, 3: west, 4: est.\r
+    fn next_movement(&mut self) -> i64 {\r
+        for (mov, pos) in self.positions_around() {\r
+            if self.get_state(pos) == LocationState::Unknown {\r
+                self.current_path.push(pos);\r
+                return mov\r
+            }\r
+        }\r
+\r
+        for (mov, pos) in self.positions_around() {\r
+            if self.get_state(pos) == LocationState::Visited {\r
+                self.set_state(self.current_position(), LocationState::DeadEnd);\r
+                self.current_path.pop();\r
+                return mov\r
+            }\r
+        }\r
+\r
+        panic!("Droid stuck");\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
+            }\r
+            1 => self.set_state(self.current_position(), LocationState::Visited),\r
+            2 => self.oxygen_found = true,\r
+            _ => panic!("Unkown droid status: {}", status)\r
+        }\r
+    }\r
+}\r
+\r
+impl intcode::IO for DroidTrackingSystem {\r
     // May block.\r
     fn read(&mut self) -> i64 {\r
-        1\r
+        self.next_movement()\r
     }\r
 \r
     // Send to the output channel.\r
     fn write(&mut self, value: i64) {\r
+        self.reply_from_droid(value);\r
     }\r
-}\r
 \r
-pub fn shorted_path_to_oxygen(code: &[i64]) -> i32 {\r
-    0\r
+    fn halt(&self) -> bool {\r
+        self.oxygen_found\r
+    }\r
 }\r
 \r
-\r
-#[cfg(test)]\r
-mod tests {\r
-    use super::*;\r
-\r
-    #[test]\r
-    fn part1_sample_1() {\r
-\r
-    }\r
+pub fn nb_of_movement_to_reach_oxygen(code: &[i64]) -> i32 {\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
 }
\ No newline at end of file
index b1968ac..c2a28df 100644 (file)
@@ -8,6 +8,7 @@ enum Mode {
 pub trait IO {\r
     fn read(&mut self) -> i64;\r
     fn write(&mut self, value: i64);\r
+    fn halt(&self) -> bool { false }\r
 }\r
 \r
 struct Buffer {\r
@@ -98,6 +99,8 @@ pub fn execute_op_code_with_custom_io(code: &[i64], io: &mut dyn IO) {
     };\r
 \r
     loop {\r
+        if io.halt() { break; }\r
+\r
         let (op, modes) = read_op_and_modes(code[cursor]);\r
 \r
         match op {\r
index f1cb88d..9b2570d 100644 (file)
@@ -112,8 +112,8 @@ fn day14() -> String {
 }
 
 fn day15() -> String {
-    //let code = common::read_list_of_numbers("data/day15.input", ",");
-    format!("part1: {}, part2: {}", "", "")
+    let code = common::read_list_of_numbers("data/day15.input", ",");
+    format!("part1: {}, part2: {}", day15::nb_of_movement_to_reach_oxygen(&code), "")
 }
 
 fn format_micros(t: u128) -> String {