Skip to main content

advent_of_code/year2016/
day08.rs

1use crate::common::character_recognition::{CHAR_HEIGHT, recognize};
2use crate::input::Input;
3
4struct Screen {
5    pixels: [bool; Self::WIDTH * CHAR_HEIGHT],
6}
7
8impl Screen {
9    const WIDTH: usize = 50;
10
11    const fn get_pixel(&self, x: usize, y: usize) -> bool {
12        self.pixels[y * Self::WIDTH + x]
13    }
14
15    const fn set_pixel(&mut self, x: usize, y: usize, on: bool) {
16        self.pixels[y * Self::WIDTH + x] = on;
17    }
18
19    fn turn_on_rect(&mut self, width: usize, height: usize) {
20        for x in 0..width {
21            for y in 0..height {
22                self.set_pixel(x, y, true);
23            }
24        }
25    }
26
27    fn rotate_row(&mut self, row: usize, amount: usize) {
28        let mut new_row = [false; Self::WIDTH];
29        for x in 0..Self::WIDTH {
30            new_row[(x + amount) % Self::WIDTH] = self.get_pixel(x, row);
31        }
32        for (x, &on) in new_row.iter().enumerate() {
33            self.set_pixel(x, row, on);
34        }
35    }
36
37    fn rotate_col(&mut self, col: usize, amount: usize) {
38        let mut new_col = [false; CHAR_HEIGHT];
39        for y in 0..CHAR_HEIGHT {
40            new_col[(y + amount) % CHAR_HEIGHT] = self.get_pixel(col, y);
41        }
42
43        for (y, &on) in new_col.iter().enumerate() {
44            self.set_pixel(col, y, on);
45        }
46    }
47
48    const fn new() -> Self {
49        Self {
50            pixels: [false; Self::WIDTH * CHAR_HEIGHT],
51        }
52    }
53}
54
55pub fn solve(input: &Input) -> Result<String, String> {
56    let mut screen = Screen::new();
57    for line in input.text.lines() {
58        if let Some(after) = line.strip_prefix("rect ") {
59            let (part1, part2) = after
60                .split_once('x')
61                .ok_or_else(|| "Invalid input".to_string())?;
62            let width = part1.parse::<usize>().map_err(|_| "Invalid input")?;
63            let height = part2.parse::<usize>().map_err(|_| "Invalid input")?;
64            screen.turn_on_rect(width, height);
65        } else if let Some(after) = line.strip_prefix("rotate row y=") {
66            let (part1, part2) = after
67                .split_once(" by ")
68                .ok_or_else(|| "invalid input".to_string())?;
69            let row_to_rotate = part1.parse::<usize>().map_err(|_| "Invalid input")?;
70            let rotation_amount = part2.parse::<usize>().map_err(|_| "Invalid input")?;
71            screen.rotate_row(row_to_rotate, rotation_amount);
72        } else if let Some(after) = line.strip_prefix("rotate column x=") {
73            let (part1, part2) = after
74                .split_once(" by ")
75                .ok_or_else(|| "invalid input".to_string())?;
76            let col_to_rotate = part1.parse::<usize>().map_err(|_| "Invalid input")?;
77            let rotation_amount = part2.parse::<usize>().map_err(|_| "Invalid input")?;
78            screen.rotate_col(col_to_rotate, rotation_amount);
79        } else {
80            return Err("Invalid line".to_string());
81        }
82    }
83
84    if input.is_part_one() {
85        Ok(screen.pixels.iter().filter(|&&p| p).count().to_string())
86    } else {
87        recognize(&screen.pixels)
88    }
89}
90
91#[test]
92pub fn tests() {
93    let real_input = include_str!("day08_input.txt");
94    test_part_one!(real_input => "128".to_string());
95    test_part_two!(real_input => "EOARGPHYAO".to_string());
96}