use super::intcode;\r
 use std::collections::HashSet;\r
 \r
-pub fn scaffold_intersections(code: &[i64]) -> i32 {\r
-    let output = intcode::execute_op_code(code, &[]);\r
-    let mut board = Vec::<Vec<char>>::new();\r
-    let mut current_line = Vec::<char>::new();\r
-\r
-    let (mut x, mut y) = (0i32, 0i32);\r
-    let mut dir = '^';\r
-\r
-    let mut current_x = 0;\r
-    for c in output {\r
-        if c == 10 {\r
-            board.push(current_line);\r
-            current_line = Vec::<char>::new();\r
-            current_x = 0;\r
-            //println!("");\r
-        } else {\r
-            let c = (c as u8) as char;\r
-            if let '^' | '<' | 'v' | '>' = c {\r
-                x = current_x;\r
-                y = board.len() as i32;\r
-                dir = c;\r
-            }\r
-            //print!("{}", c);\r
-            current_line.push(c);\r
-            current_x += 1;\r
+pub struct RobotTrackingSystem {\r
+    output: Vec<i64>,\r
+    board: Vec<Vec<char>>,\r
+    start_position: (i32, i32),\r
+    start_dir: char,\r
+}\r
+\r
+impl RobotTrackingSystem {\r
+    fn new() -> Self {\r
+        RobotTrackingSystem {\r
+            output: Vec::new(),\r
+            board: Vec::<Vec<char>>::new(),\r
+            start_position: (0, 0),\r
+            start_dir: '^',\r
         }\r
     }\r
 \r
-    let get = |x: i32, y: i32| -> Option<char> {\r
-        if x < board[0].len() as i32 && x >= 0 && y < board.len() as i32 && y >= 0 {\r
-            Some(board[y as usize][x as usize])\r
+    fn get(&self, x: i32, y: i32) -> Option<char> {\r
+        if x < self.board[0].len() as i32 && x >= 0 && y < self.board.len() as i32 && y >= 0 {\r
+            Some(self.board[y as usize][x as usize])\r
         } else {\r
             None\r
         }\r
-    };\r
+    }\r
+\r
+    fn build_board_from_output(&mut self) {\r
+        // If the board has already been read.\r
+        if !self.board.is_empty() {\r
+            return;\r
+        }\r
+\r
+        let mut current_line = Vec::<char>::new();\r
+        let mut current_x = 0;\r
+        for c in self.output.iter() {\r
+            if *c == 10 {\r
+                self.board.push(current_line);\r
+                current_line = Vec::<char>::new();\r
+                current_x = 0;\r
+            } else {\r
+                let c = (*c as u8) as char;\r
+                if let '^' | '<' | 'v' | '>' = c {\r
+                    self.start_position = (current_x, self.board.len() as i32);\r
+                    self.start_dir = c;\r
+                }\r
+                current_line.push(c);\r
+                current_x += 1;\r
+            }\r
+        }\r
+    }\r
+}\r
 \r
+impl intcode::IO for RobotTrackingSystem {\r
+    // May block.\r
+    fn read(&mut self) -> i64 {\r
+        self.build_board_from_output();\r
+        42\r
+    }\r
+\r
+    // Send to the output channel.\r
+    fn write(&mut self, value: i64) {\r
+        self.output.push(value);\r
+    }\r
+\r
+    fn finished(&mut self) {\r
+        self.build_board_from_output();\r
+    }\r
+}\r
+\r
+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
         let positions = [('^', (x, y - 1)), ('<', (x - 1, y)), ('>', (x + 1, y)), ('v', (x, y + 1))];\r
 \r
         let next_position = positions.iter().find(|(d, _)| *d == dir).unwrap().1;\r
-            //match dir { '^' => positions[0], '<' => positions[1], '>' => positions[2], 'v' | _ => positions[3] };\r
 \r
         // If the robot can continue straightforward.\r
-        if get(next_position.0, next_position.1) == Some('#') {\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
         }\r
 \r
         for (d, p) in &positions {\r
-            if get(p.0, p.1) == Some('#') && !visited_locations.contains(p) {\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
     }\r
 \r
     crosses.iter().fold(0, |sum, cross| sum + cross.0 * cross.1)\r
+}\r
+\r
+pub fn part2(code: &[i64]) {\r
+\r
 }
\ No newline at end of file