Advent of Code 2019 - Day 11

2 min read

After the angle madness of yesterday today's challenge was quite relaxing.

We had to use our finished intcode computer to move a robot over panels to paint them and according to the color of the current panel make it move it different directions.

Code

use std::collections::HashMap;
use utils::intcode::{ExitCode, VM};
use utils::{Direction, Point};

fn paint_panels(vm: &mut VM, start_char: char) -> HashMap<Point, char> {
    let mut current_direction = Direction::Up;
    let mut panels: HashMap<Point, char> = HashMap::new();
    let mut current_point = Point { x: 0, y: 0 };
    panels.insert(current_point.clone(), start_char);

    loop {
        let current_color = panels.entry(current_point.clone()).or_insert('.');
        let vm_input = match current_color {
            '.' => 0,
            '#' => 1,
            _ => panic!("Invalid character!"),
        };

        vm.add_input(vm_input);

        if vm.run() == ExitCode::Stop {
            break;
        }

        match vm.get_output() {
            0 => panels.insert(current_point.clone(), '.'),
            1 => panels.insert(current_point.clone(), '#'),
            _ => panic!("Invalid output!"),
        };

        match vm.get_output() {
            0 => current_direction = current_direction.turn_left(),
            1 => current_direction = current_direction.turn_right(),
            _ => panic!("Invalid output!"),
        };

        let mov = match current_direction {
            Direction::Up => Point { x: 0, y: 1 },
            Direction::Down => Point { x: 0, y: -1 },
            Direction::Left => Point { x: -1, y: 0 },
            Direction::Right => Point { x: 1, y: 0 },
        };
        current_point.add(&mov);
    }
    panels
}

fn print_registration_identifier(map: &mut HashMap<Point, char>) {
    let min_x = map.keys().min_by_key(|x| x.x).unwrap().x;
    let max_x = map.keys().max_by_key(|x| x.x).unwrap().x;
    let min_y = map.keys().min_by_key(|x| x.y).unwrap().y;
    let max_y = map.keys().max_by_key(|x| x.y).unwrap().y;
    for y in (min_y..=max_y).rev() {
        for x in min_x..=max_x {
            let output = match map.entry(Point { x, y }).or_insert('.') {
                '.' => ' ',
                '#' => '#',
                _ => panic!("Invalid character!"),
            };
            print!("{}", output);
        }
        println!();
    }
}

pub fn part_one(input: &str) -> i32 {
    let mut vm = VM::from(input);
    let panels = paint_panels(&mut vm, '.');
    panels.len() as i32
}

pub fn part_two(input: &str) {
    let mut vm = VM::from(input);
    let mut panels = paint_panels(&mut vm, '#');
    print_registration_identifier(&mut panels);
}

Benchmarks

2019 - Day 11 - Part 1 time: 52.580546ms
2019 - Day 11 - Part 2 time: 4.656708ms