aoc2019/day11/src/main.rs

108 lines
2.7 KiB
Rust

use shared::intcode::{IntCode, SimulateStep};
use std::collections::{HashMap, HashSet};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Direction {
Up,
Right,
Down,
Left,
}
impl Direction {
pub fn turn_right(self) -> Self {
match self {
Self::Up => Self::Right,
Self::Right => Self::Down,
Self::Down => Self::Left,
Self::Left => Self::Up,
}
}
pub fn turn_left(self) -> Self {
match self {
Self::Up => Self::Left,
Self::Right => Self::Up,
Self::Down => Self::Right,
Self::Left => Self::Down,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Position {
pub x: isize,
pub y: isize,
}
impl std::ops::Add<Direction> for Position {
type Output = Position;
fn add(mut self, rhs: Direction) -> Self::Output {
match rhs {
Direction::Up => self.y -= 1,
Direction::Right => self.x += 1,
Direction::Down => self.y += 1,
Direction::Left => self.x -= 1,
}
self
}
}
fn paint(mut ic: IntCode, start_white: bool) -> HashMap<Position, bool> {
let mut painted = HashMap::new();
let mut pos = Position { x: 0, y: 0 };
let mut direction = Direction::Up;
if start_white {
painted.insert(pos, true);
}
loop {
let is_white = painted.get(&pos).cloned().unwrap_or(false);
ic.next_input = Some(if is_white { 1 } else { 0 });
match ic.simulate_step() {
SimulateStep::WaitForInput => panic!("no further input until paint and movement done"),
SimulateStep::Finished => break,
SimulateStep::Output(n) => {
match n {
0 => { painted.insert(pos, false); },
1 => { painted.insert(pos, true); },
_ => panic!("invalid paint: {}", n),
}
}
}
match ic.simulate_step().expect_output() {
0 => direction = direction.turn_left(),
1 => direction = direction.turn_right(),
n => panic!("invalid rotation: {}", n),
}
pos = pos + direction;
}
painted
}
fn visualize(painted: HashMap<Position, bool>) {
let painted_white: HashSet<Position> = painted.into_iter().filter_map(|(k, v)| if v { Some(k) } else { None }).collect();
let left = painted_white.iter().map(|p| p.x).min().unwrap();
let right = painted_white.iter().map(|p| p.x).max().unwrap();
let top = painted_white.iter().map(|p| p.y).min().unwrap();
let bottom = painted_white.iter().map(|p| p.y).max().unwrap();
for y in top..=bottom {
for x in left..=right {
if painted_white.contains(&Position { x, y }) {
print!("#");
} else {
print!(" ");
}
}
println!("");
}
}
fn main() {
let ic = include_str!("input.txt").parse::<IntCode>().unwrap();
let painted = paint(ic.clone(), false);
println!("First try: Painted {} tiles.", painted.len());
let painted = paint(ic, true);
visualize(painted);
}