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