mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-12-18 18:29:55 +00:00
Day 11
This commit is contained in:
parent
2f53e2ac8b
commit
672b0964a1
5 changed files with 202 additions and 9 deletions
151
2019/src/bin/day11.rs
Normal file
151
2019/src/bin/day11.rs
Normal 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!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue