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