Add movements (part2, WIP)
authorGrégory Burri <gregory.burri@matisa.ch>
Fri, 20 Dec 2019 08:52:38 +0000 (09:52 +0100)
committerGrégory Burri <gregory.burri@matisa.ch>
Fri, 20 Dec 2019 08:52:38 +0000 (09:52 +0100)
src/day17.rs

index 6998995..c64ed0e 100644 (file)
@@ -1,7 +1,7 @@
 use super::intcode;\r
 use std::collections::HashSet;\r
 \r
-#[derive(PartialEq, Eq, Copy, Clone)]\r
+#[derive(PartialEq, Eq, Copy, Clone, Debug)]\r
 enum Direction { Up, Left, Down, Right }\r
 \r
 impl Direction {\r
@@ -16,14 +16,19 @@ impl Direction {
     }\r
 }\r
 \r
-#[derive(PartialEq, Eq, Copy, Clone)]\r
-struct MovementCommand { dir: Direction, steps: u32 }\r
+#[derive(PartialEq, Eq, Copy, Clone, Debug)]\r
+enum Movement { Left, Right }\r
+\r
+#[derive(PartialEq, Eq, Copy, Clone, Debug)]\r
+struct MovementCommand { mov: Movement, steps: u32 }\r
 \r
 pub struct RobotTrackingSystem {\r
     output: Vec<i64>,\r
     board: Vec<Vec<char>>,\r
     start_position: (i32, i32),\r
     start_dir: Direction,\r
+    crossings: Vec<(i32, i32)>,\r
+    dir_commands: Vec<MovementCommand>,\r
 }\r
 \r
 impl RobotTrackingSystem {\r
@@ -33,6 +38,8 @@ impl RobotTrackingSystem {
             board: Vec::<Vec<char>>::new(),\r
             start_position: (0, 0),\r
             start_dir: Direction::Up,\r
+            crossings: Vec::<(i32, i32)>::new(),\r
+            dir_commands: Vec::<MovementCommand>::new(),\r
         }\r
     }\r
 \r
@@ -68,6 +75,63 @@ impl RobotTrackingSystem {
                 current_x += 1;\r
             }\r
         }\r
+\r
+        self.output.clear();\r
+        self.run_through();\r
+    }\r
+\r
+    // Run the path and find the crossings and define the movements.\r
+    fn run_through(&mut self) {\r
+        let (mut x, mut y) = self.start_position;\r
+        let mut dir = self.start_dir;\r
+        let mut visited_locations = HashSet::<(i32, i32)>::new();\r
+        visited_locations.insert((x, y));\r
+\r
+        let mut last_mov = Movement::Left;\r
+        let mut steps = 0;\r
+\r
+        'main: loop {\r
+            let positions = [(Direction::Up, (x, y - 1)), (Direction::Left, (x - 1, y)), (Direction::Right, (x + 1, y)), (Direction::Down, (x, y + 1))];\r
+\r
+            let next_position = positions.iter().find(|(d, _)| *d == dir).unwrap().1;\r
+\r
+            // If the robot can continue straightforward.\r
+            if self.get(next_position.0, next_position.1) == Some('#') {\r
+                if !visited_locations.insert(next_position) {\r
+                    self.crossings.push(next_position);\r
+                }\r
+                steps += 1;\r
+                x = next_position.0;\r
+                y = next_position.1;\r
+                continue;\r
+            }\r
+\r
+            if steps != 0 {\r
+                self.dir_commands.push(MovementCommand { mov: last_mov, steps });\r
+                steps = 0;\r
+            }\r
+\r
+            for (d, p) in &positions {\r
+                if self.get(p.0, p.1) == Some('#') && !visited_locations.contains(p) {\r
+\r
+                    last_mov =\r
+                        match (dir, *d) {\r
+                            (Direction::Up, Direction::Right) | (Direction::Right, Direction::Down) | (Direction::Down, Direction::Left) | (Direction::Left, Direction::Up) => Movement::Right,\r
+                            (Direction::Up, Direction::Left) | (Direction::Left, Direction::Down) | (Direction::Down, Direction::Right) | (Direction::Right, Direction::Up) => Movement::Left,\r
+                            _ => panic!("Unable to find a movement from {:?} to {:?}", dir, *d)\r
+                        };\r
+\r
+                    visited_locations.insert(*p);\r
+                    steps += 1;\r
+                    dir = *d;\r
+                    x = p.0;\r
+                    y = p.1;\r
+                    continue 'main;\r
+                }\r
+            }\r
+\r
+            break;\r
+        }\r
     }\r
 }\r
 \r
@@ -75,7 +139,7 @@ impl intcode::IO for RobotTrackingSystem {
     // May block.\r
     fn read(&mut self) -> i64 {\r
         self.build_board_from_output();\r
-        42\r
+        42 // TODO: part2.\r
     }\r
 \r
     // Send to the output channel.\r
@@ -91,44 +155,11 @@ impl intcode::IO for RobotTrackingSystem {
 pub fn scaffold_intersections(code: &[i64]) -> i32 {\r
     let mut rts = RobotTrackingSystem::new();\r
     intcode::execute_op_code_with_custom_io(code, &mut rts);\r
-\r
-    let (mut x, mut y) = rts.start_position;\r
-    let mut dir = rts.start_dir;\r
-    let mut visited_locations = HashSet::<(i32, i32)>::new();\r
-    let mut crosses = Vec::<(i32, i32)>::new();\r
-    visited_locations.insert((x, y));\r
-\r
-    'main: loop {\r
-        let positions = [(Direction::Up, (x, y - 1)), (Direction::Left, (x - 1, y)), (Direction::Right, (x + 1, y)), (Direction::Down, (x, y + 1))];\r
-\r
-        let next_position = positions.iter().find(|(d, _)| *d == dir).unwrap().1;\r
-\r
-        // If the robot can continue straightforward.\r
-        if rts.get(next_position.0, next_position.1) == Some('#') {\r
-            if !visited_locations.insert(next_position) {\r
-                crosses.push(next_position);\r
-            }\r
-            x = next_position.0;\r
-            y = next_position.1;\r
-            continue;\r
-        }\r
-\r
-        for (d, p) in &positions {\r
-            if rts.get(p.0, p.1) == Some('#') && !visited_locations.contains(p) {\r
-                visited_locations.insert(*p);\r
-                dir = *d;\r
-                x = p.0;\r
-                y = p.1;\r
-                continue 'main;\r
-            }\r
-        }\r
-\r
-        break;\r
-    }\r
-\r
-    crosses.iter().fold(0, |sum, cross| sum + cross.0 * cross.1)\r
+    rts.crossings.iter().fold(0, |sum, crossing| sum + crossing.0 * crossing.1)\r
 }\r
 \r
 pub fn part2(code: &[i64]) {\r
+    let mut rts = RobotTrackingSystem::new();\r
+    intcode::execute_op_code_with_custom_io(code, &mut rts);\r
 \r
-}
\ No newline at end of file
+}\r