From 672b0964a103b0abcca662c1575d1e5064202ee6 Mon Sep 17 00:00:00 2001 From: Wesley Moore Date: Wed, 11 Dec 2019 22:14:39 +1100 Subject: [PATCH] Day 11 --- 2019/src/bin/day11.rs | 151 ++++++++++++++++++++++++++++++++++++++++++ 2019/src/bin/day5.rs | 4 +- 2019/src/bin/day7.rs | 2 +- 2019/src/bin/day9.rs | 10 +-- 2019/src/computer.rs | 44 +++++++++++- 5 files changed, 202 insertions(+), 9 deletions(-) create mode 100644 2019/src/bin/day11.rs diff --git a/2019/src/bin/day11.rs b/2019/src/bin/day11.rs new file mode 100644 index 0000000..17b8e3a --- /dev/null +++ b/2019/src/bin/day11.rs @@ -0,0 +1,151 @@ +use std::{fs, io}; + +use advent_of_code::computer::{ComputeResult, Computer}; +use advent_of_code::input; +use advent_of_code::point::Point; +use std::collections::HashMap; + +#[derive(Debug)] +enum Rotate { + Left, + Right, +} + +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +enum Direction { + North, + South, + East, + West, +} + +#[derive(Debug)] +struct Robot { + heading: Direction, + position: Point, +} + +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +enum Colour { + Black, + White, +} + +fn main() -> io::Result<()> { + let input = fs::read_to_string("input/day11.txt")?; + let program = input::read_separated_line(',', &input)?; + + let painted = run_robot(Colour::Black, program.clone()); + println!("Part 1: {}", painted.len()); + + let painted = run_robot(Colour::White, program.clone()); + // Determine dimensions of image + let minx = painted.iter().map(|(point, _)| point.0).min().unwrap(); + let maxx = painted.iter().map(|(point, _)| point.0).max().unwrap(); + let miny = painted.iter().map(|(point, _)| point.1).min().unwrap(); + let maxy = painted.iter().map(|(point, _)| point.1).max().unwrap(); + + println!(); + for y in (miny..=maxy).rev() { + for x in minx..=maxx { + match painted.get(&Point(x, y)) { + Some(Colour::White) => print!("█"), + Some(Colour::Black) | None => print!(" "), + } + } + println!(); + } + println!(); + + Ok(()) +} + +fn run_robot(initial_colour: Colour, program: Vec) -> HashMap { + let mut robot = Robot::new(); + let mut painted = HashMap::new(); + let initial_input = match initial_colour { + Colour::Black => 0, + Colour::White => 1, + }; + let mut computer = Computer::new('1', program, vec![initial_input], vec![]); + + loop { + match computer.run(None, None) { + ComputeResult::Halted => break, + ComputeResult::NeedsInput => { + let output = computer.output().to_vec(); + painted.insert(robot.position, Colour::from(output[0])); + let rotation = Rotate::from(output[1]); + robot.rotate(rotation); + robot.go_forward(); + computer.clear_output(); + + let tile_colour = painted + .get(&robot.position) + .map(|colour| match colour { + Colour::Black => 0, + Colour::White => 1, + }) + .unwrap_or(0); + computer.input(tile_colour); + } + } + } + + painted +} + +impl Robot { + fn new() -> Self { + Robot { + heading: Direction::North, + position: Point(0, 0), + } + } + + fn rotate(&mut self, rotate: Rotate) { + self.heading = match rotate { + Rotate::Left => match self.heading { + Direction::North => Direction::West, + Direction::South => Direction::East, + Direction::East => Direction::North, + Direction::West => Direction::South, + }, + Rotate::Right => match self.heading { + Direction::North => Direction::East, + Direction::South => Direction::West, + Direction::East => Direction::South, + Direction::West => Direction::North, + }, + } + } + + fn go_forward(&mut self) { + match self.heading { + Direction::North => self.position.1 += 1, + Direction::South => self.position.1 -= 1, + Direction::East => self.position.0 += 1, + Direction::West => self.position.0 -= 1, + } + } +} + +impl From for Rotate { + fn from(n: i64) -> Self { + match n { + 0 => Rotate::Left, + 1 => Rotate::Right, + _ => unreachable!(), + } + } +} + +impl From for Colour { + fn from(n: i64) -> Self { + match n { + 0 => Colour::Black, + 1 => Colour::White, + _ => unreachable!(), + } + } +} diff --git a/2019/src/bin/day5.rs b/2019/src/bin/day5.rs index 43c8b80..37709df 100644 --- a/2019/src/bin/day5.rs +++ b/2019/src/bin/day5.rs @@ -7,11 +7,11 @@ fn main() -> io::Result<()> { let mut computer = computer::Computer::new('1', data.clone(), vec![1], vec![]); computer.run(None, None); - println!("Part 1: {}", computer.output()); + println!("Part 1: {}", computer.last_output()); let mut computer = computer::Computer::new('2', data.clone(), vec![5], vec![]); computer.run(None, None); - println!("Part 2: {}", computer.output()); + println!("Part 2: {}", computer.last_output()); Ok(()) } diff --git a/2019/src/bin/day7.rs b/2019/src/bin/day7.rs index f8a3b9a..497d72a 100644 --- a/2019/src/bin/day7.rs +++ b/2019/src/bin/day7.rs @@ -33,7 +33,7 @@ fn part1(data: Vec) { let mut computer = Computer::new(name, data.clone(), input, vec![]); name = char::try_from(name as u32 + 1).unwrap(); computer.run(None, None); - output = computer.output(); + output = computer.last_output(); } output }) diff --git a/2019/src/bin/day9.rs b/2019/src/bin/day9.rs index 8f8d6ef..d470f06 100644 --- a/2019/src/bin/day9.rs +++ b/2019/src/bin/day9.rs @@ -9,11 +9,11 @@ fn main() -> io::Result<()> { let mut computer = Computer::new('1', program.clone(), vec![1], vec![]); computer.run(None, None); - println!("Part 1: {}", computer.output()); + println!("Part 1: {}", computer.last_output()); let mut computer = Computer::new('2', program.clone(), vec![2], vec![]); computer.run(None, None); - println!("Part 2: {}", computer.output()); + println!("Part 2: {}", computer.last_output()); Ok(()) } @@ -28,7 +28,7 @@ mod tests { let mut computer = Computer::new('T', program, vec![], vec![]); computer.run(None, None); - assert_eq!(computer.output(), 1219070632396864); + assert_eq!(computer.last_output(), 1219070632396864); } #[test] @@ -39,7 +39,7 @@ mod tests { let mut computer = Computer::new('T', program, vec![], vec![]); computer.run(None, None); - assert_eq!(computer.output(), 99); + assert_eq!(computer.last_output(), 99); } #[test] @@ -48,6 +48,6 @@ mod tests { let mut computer = Computer::new('T', program, vec![], vec![]); computer.run(None, None); - assert_eq!(computer.output(), 1125899906842624); + assert_eq!(computer.last_output(), 1125899906842624); } } diff --git a/2019/src/computer.rs b/2019/src/computer.rs index e150743..480aa6c 100644 --- a/2019/src/computer.rs +++ b/2019/src/computer.rs @@ -51,18 +51,28 @@ pub struct Computer { pub trait Input { fn read(&mut self) -> Option; + + fn push(&mut self, val: i64); } pub trait Output { fn write(&mut self, value: i64); fn last_value(&self) -> i64; + + fn get(&self) -> &[i64]; + + fn clear(&mut self); } impl Input for Vec { fn read(&mut self) -> Option { self.pop() } + + fn push(&mut self, val: i64) { + self.insert(0, val) + } } impl Output for Vec { @@ -73,12 +83,24 @@ impl Output for Vec { fn last_value(&self) -> i64 { *self.last().unwrap() } + + fn get(&self) -> &[i64] { + self + } + + fn clear(&mut self) { + self.clear() + } } impl Input for Rc> { fn read(&mut self) -> Option { dbg!(self.borrow_mut().queue.pop_front()) } + + fn push(&mut self, val: i64) { + self.borrow_mut().queue.push_back(val) + } } impl Output for Rc> { @@ -91,6 +113,14 @@ impl Output for Rc> { fn last_value(&self) -> i64 { self.borrow().last.unwrap() } + + fn get(&self) -> &[i64] { + unimplemented!() + } + + fn clear(&mut self) { + unimplemented!() + } } fn decode(mut instruction: i64) -> Instruction { @@ -253,9 +283,21 @@ where } } - pub fn output(&self) -> i64 { + pub fn last_output(&self) -> i64 { self.output.last_value() } + + pub fn input(&mut self, val: i64) { + self.input.push(val) + } + + pub fn output(&self) -> &[i64] { + self.output.get() + } + + pub fn clear_output(&mut self) { + self.output.clear() + } } impl Pipe {