This commit is contained in:
Wesley Moore 2019-12-11 22:14:39 +11:00
parent 2f53e2ac8b
commit 672b0964a1
No known key found for this signature in database
GPG key ID: BF67766C0BC2D0EE
5 changed files with 202 additions and 9 deletions

151
2019/src/bin/day11.rs Normal file
View file

@ -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<i64>) -> HashMap<Point, Colour> {
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<i64> for Rotate {
fn from(n: i64) -> Self {
match n {
0 => Rotate::Left,
1 => Rotate::Right,
_ => unreachable!(),
}
}
}
impl From<i64> for Colour {
fn from(n: i64) -> Self {
match n {
0 => Colour::Black,
1 => Colour::White,
_ => unreachable!(),
}
}
}

View file

@ -7,11 +7,11 @@ fn main() -> io::Result<()> {
let mut computer = computer::Computer::new('1', data.clone(), vec![1], vec![]); let mut computer = computer::Computer::new('1', data.clone(), vec![1], vec![]);
computer.run(None, None); 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![]); let mut computer = computer::Computer::new('2', data.clone(), vec![5], vec![]);
computer.run(None, None); computer.run(None, None);
println!("Part 2: {}", computer.output()); println!("Part 2: {}", computer.last_output());
Ok(()) Ok(())
} }

View file

@ -33,7 +33,7 @@ fn part1(data: Vec<i64>) {
let mut computer = Computer::new(name, data.clone(), input, vec![]); let mut computer = Computer::new(name, data.clone(), input, vec![]);
name = char::try_from(name as u32 + 1).unwrap(); name = char::try_from(name as u32 + 1).unwrap();
computer.run(None, None); computer.run(None, None);
output = computer.output(); output = computer.last_output();
} }
output output
}) })

View file

@ -9,11 +9,11 @@ fn main() -> io::Result<()> {
let mut computer = Computer::new('1', program.clone(), vec![1], vec![]); let mut computer = Computer::new('1', program.clone(), vec![1], vec![]);
computer.run(None, None); 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![]); let mut computer = Computer::new('2', program.clone(), vec![2], vec![]);
computer.run(None, None); computer.run(None, None);
println!("Part 2: {}", computer.output()); println!("Part 2: {}", computer.last_output());
Ok(()) Ok(())
} }
@ -28,7 +28,7 @@ mod tests {
let mut computer = Computer::new('T', program, vec![], vec![]); let mut computer = Computer::new('T', program, vec![], vec![]);
computer.run(None, None); computer.run(None, None);
assert_eq!(computer.output(), 1219070632396864); assert_eq!(computer.last_output(), 1219070632396864);
} }
#[test] #[test]
@ -39,7 +39,7 @@ mod tests {
let mut computer = Computer::new('T', program, vec![], vec![]); let mut computer = Computer::new('T', program, vec![], vec![]);
computer.run(None, None); computer.run(None, None);
assert_eq!(computer.output(), 99); assert_eq!(computer.last_output(), 99);
} }
#[test] #[test]
@ -48,6 +48,6 @@ mod tests {
let mut computer = Computer::new('T', program, vec![], vec![]); let mut computer = Computer::new('T', program, vec![], vec![]);
computer.run(None, None); computer.run(None, None);
assert_eq!(computer.output(), 1125899906842624); assert_eq!(computer.last_output(), 1125899906842624);
} }
} }

View file

@ -51,18 +51,28 @@ pub struct Computer<I: Input, O: Output> {
pub trait Input { pub trait Input {
fn read(&mut self) -> Option<i64>; fn read(&mut self) -> Option<i64>;
fn push(&mut self, val: i64);
} }
pub trait Output { pub trait Output {
fn write(&mut self, value: i64); fn write(&mut self, value: i64);
fn last_value(&self) -> i64; fn last_value(&self) -> i64;
fn get(&self) -> &[i64];
fn clear(&mut self);
} }
impl Input for Vec<i64> { impl Input for Vec<i64> {
fn read(&mut self) -> Option<i64> { fn read(&mut self) -> Option<i64> {
self.pop() self.pop()
} }
fn push(&mut self, val: i64) {
self.insert(0, val)
}
} }
impl Output for Vec<i64> { impl Output for Vec<i64> {
@ -73,12 +83,24 @@ impl Output for Vec<i64> {
fn last_value(&self) -> i64 { fn last_value(&self) -> i64 {
*self.last().unwrap() *self.last().unwrap()
} }
fn get(&self) -> &[i64] {
self
}
fn clear(&mut self) {
self.clear()
}
} }
impl Input for Rc<RefCell<Pipe>> { impl Input for Rc<RefCell<Pipe>> {
fn read(&mut self) -> Option<i64> { fn read(&mut self) -> Option<i64> {
dbg!(self.borrow_mut().queue.pop_front()) dbg!(self.borrow_mut().queue.pop_front())
} }
fn push(&mut self, val: i64) {
self.borrow_mut().queue.push_back(val)
}
} }
impl Output for Rc<RefCell<Pipe>> { impl Output for Rc<RefCell<Pipe>> {
@ -91,6 +113,14 @@ impl Output for Rc<RefCell<Pipe>> {
fn last_value(&self) -> i64 { fn last_value(&self) -> i64 {
self.borrow().last.unwrap() self.borrow().last.unwrap()
} }
fn get(&self) -> &[i64] {
unimplemented!()
}
fn clear(&mut self) {
unimplemented!()
}
} }
fn decode(mut instruction: i64) -> Instruction { 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() 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 { impl Pipe {