From: Ummon Date: Mon, 16 Dec 2019 22:38:26 +0000 (+0100) Subject: Day 15 part 1 X-Git-Url: http://git.euphorik.ch/index.cgi?a=commitdiff_plain;h=61b1389ce0552c4d0b264ce16393f46dc382b08e;p=advent_of_code_2019.git Day 15 part 1 --- diff --git a/src/day15.rs b/src/day15.rs index 8e59e65..5e6b653 100644 --- a/src/day15.rs +++ b/src/day15.rs @@ -1,30 +1,100 @@ use super::intcode; +use std::iter::FromIterator; +use std::collections::HashMap; -struct RepairDroid { +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +enum LocationState { + Unknown, + Wall, + Visited, + DeadEnd, } -impl intcode::IO for RepairDroid { +struct DroidTrackingSystem { + board: HashMap<(i32, i32), LocationState>, + current_path: Vec<(i32, i32)>, + oxygen_found: bool +} + +impl DroidTrackingSystem { + fn new() -> DroidTrackingSystem { + DroidTrackingSystem { + board: HashMap::from_iter(vec![((0, 0), LocationState::Visited)].into_iter()), + current_path: vec![(0, 0)], + oxygen_found: false + } + } + + fn current_position(&self) -> (i32, i32) { *self.current_path.last().unwrap() } + + fn positions_around(&self) -> Vec<(i64, (i32, i32))> { + let (x, y) = self.current_position(); + vec![(1, (x, y + 1)), (2, (x, y - 1)), (3, (x - 1, y)), (4, (x + 1, y))] + } + + fn get_state(&self, position: (i32, i32)) -> LocationState { + match self.board.get(&position) { + Some(state) => *state, + None => LocationState::Unknown + } + } + + fn set_state(&mut self, position: (i32, i32), state: LocationState) { + self.board.insert(position, state); + } + + // 1: north, 2: south, 3: west, 4: est. + fn next_movement(&mut self) -> i64 { + for (mov, pos) in self.positions_around() { + if self.get_state(pos) == LocationState::Unknown { + self.current_path.push(pos); + return mov + } + } + + for (mov, pos) in self.positions_around() { + if self.get_state(pos) == LocationState::Visited { + self.set_state(self.current_position(), LocationState::DeadEnd); + self.current_path.pop(); + return mov + } + } + + panic!("Droid stuck"); + } + + // 0: droid hit a wall, 1: droid moved one step, 2: droid moved one step and has found the oxygen system. + fn reply_from_droid(&mut self, status: i64) { + match status { + 0 => { + self.set_state(self.current_position(), LocationState::Wall); + self.current_path.pop(); + } + 1 => self.set_state(self.current_position(), LocationState::Visited), + 2 => self.oxygen_found = true, + _ => panic!("Unkown droid status: {}", status) + } + } +} + +impl intcode::IO for DroidTrackingSystem { // May block. fn read(&mut self) -> i64 { - 1 + self.next_movement() } // Send to the output channel. fn write(&mut self, value: i64) { + self.reply_from_droid(value); } -} -pub fn shorted_path_to_oxygen(code: &[i64]) -> i32 { - 0 + fn halt(&self) -> bool { + self.oxygen_found + } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn part1_sample_1() { - - } +pub fn nb_of_movement_to_reach_oxygen(code: &[i64]) -> i32 { + let mut dts = DroidTrackingSystem::new(); + intcode::execute_op_code_with_custom_io(code, &mut dts); + dts.current_path.len() as i32 - 1 } \ No newline at end of file diff --git a/src/intcode.rs b/src/intcode.rs index b1968ac..c2a28df 100644 --- a/src/intcode.rs +++ b/src/intcode.rs @@ -8,6 +8,7 @@ enum Mode { pub trait IO { fn read(&mut self) -> i64; fn write(&mut self, value: i64); + fn halt(&self) -> bool { false } } struct Buffer { @@ -98,6 +99,8 @@ pub fn execute_op_code_with_custom_io(code: &[i64], io: &mut dyn IO) { }; loop { + if io.halt() { break; } + let (op, modes) = read_op_and_modes(code[cursor]); match op { diff --git a/src/main.rs b/src/main.rs index f1cb88d..9b2570d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 {