108 lines
2.7 KiB
Rust
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);
|
|
}
|