year2016/
day08.rs

1use utils::prelude::*;
2
3/// Converting pixels to text.
4#[derive(Clone, Debug)]
5pub struct Day08 {
6    grid: [[bool; 50]; 6],
7}
8
9#[derive(Copy, Clone, Debug)]
10enum Instruction {
11    Rect { width: u32, height: u32 },
12    RotateRow { y: u32, by: u32 },
13    RotateCol { x: u32, by: u32 },
14}
15
16impl Day08 {
17    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
18        let rect = parser::u32()
19            .with_prefix("rect ")
20            .with_suffix("x")
21            .then(parser::u32())
22            .map(|(width, height)| Instruction::Rect { width, height });
23        let rotate_row = parser::u32()
24            .with_prefix("rotate row y=")
25            .with_suffix(" by ")
26            .then(parser::u32())
27            .map(|(y, by)| Instruction::RotateRow { y, by });
28        let rotate_col = parser::u32()
29            .with_prefix("rotate column x=")
30            .with_suffix(" by ")
31            .then(parser::u32())
32            .map(|(x, by)| Instruction::RotateCol { x, by });
33
34        let mut grid = [[false; 50]; 6];
35        for item in parser::one_of((rect, rotate_row, rotate_col))
36            .with_suffix(parser::eol())
37            .parse_iterator(input)
38        {
39            match item? {
40                Instruction::Rect { width, height } => {
41                    for row in &mut grid[..height as usize] {
42                        row[..width as usize].fill(true);
43                    }
44                }
45                Instruction::RotateRow { y, by } => grid[y as usize].rotate_right(by as usize),
46                Instruction::RotateCol { x, by } => {
47                    let col = grid.map(|row| row[x as usize]);
48                    for y in 0..6 {
49                        grid[y][x as usize] = col[(y + 6 - by as usize) % 6];
50                    }
51                }
52            }
53        }
54
55        Ok(Self { grid })
56    }
57
58    #[must_use]
59    pub fn part1(&self) -> usize {
60        self.grid.as_flattened().iter().filter(|&&x| x).count()
61    }
62
63    #[must_use]
64    pub fn part2(&self) -> String {
65        let mut output = String::with_capacity(10);
66
67        for i in (0..50).step_by(5) {
68            let mut letter = 0;
69            for row in self.grid {
70                for &b in &row[i..i + 5] {
71                    letter <<= 1;
72                    if b {
73                        letter |= 1;
74                    }
75                }
76            }
77            output.push(Self::ocr(letter));
78        }
79
80        output
81    }
82
83    fn ocr(letter: u32) -> char {
84        //  ##  ###   ##  #### ####  ##  #  #  ###   ## #  # #     ##  ###  ###   ### #  # #   #####
85        // #  # #  # #  # #    #    #  # #  #   #     # # #  #    #  # #  # #  # #    #  # #   #   #
86        // #  # ###  #    ###  ###  #    ####   #     # ##   #    #  # #  # #  # #    #  #  # #   #
87        // #### #  # #    #    #    # ## #  #   #     # # #  #    #  # ###  ###   ##  #  #   #   #
88        // #  # #  # #  # #    #    #  # #  #   #  #  # # #  #    #  # #    # #     # #  #   #  #
89        // #  # ###   ##  #### #     ### #  #  ###  ##  #  # ####  ##  #    #  # ###   ##    #  ####
90        match letter {
91            //111112222233333444445555566666
92            0b011001001010010111101001010010 => 'A',
93            0b111001001011100100101001011100 => 'B',
94            0b011001001010000100001001001100 => 'C',
95            0b111101000011100100001000011110 => 'E',
96            0b111101000011100100001000010000 => 'F',
97            0b011001001010000101101001001110 => 'G',
98            0b100101001011110100101001010010 => 'H',
99            0b011100010000100001000010001110 => 'I',
100            0b001100001000010000101001001100 => 'J',
101            0b100101010011000101001010010010 => 'K',
102            0b100001000010000100001000011110 => 'L',
103            0b011001001010010100101001001100 => 'O',
104            0b111001001010010111001000010000 => 'P',
105            0b111001001010010111001010010010 => 'R',
106            0b011101000010000011000001011100 => 'S',
107            0b100101001010010100101001001100 => 'U',
108            0b100011000101010001000010000100 => 'Y',
109            0b111100001000100010001000011110 => 'Z',
110            _ => {
111                let mut display = String::new();
112                for b in (0..30).rev() {
113                    display.push(if letter & (1 << b) == 0 { ' ' } else { '#' });
114                    if b % 5 == 0 {
115                        display.push('\n');
116                    }
117                }
118                panic!("unknown letter {letter:#032b}:\n{display}");
119            }
120        }
121    }
122}
123
124examples!(Day08 -> (usize, &'static str) [
125    {
126        input: "rect 3x2\n\
127            rotate column x=1 by 1\n\
128            rotate row y=0 by 4\n\
129            rotate column x=1 by 1",
130        part1: 6,
131    },
132]);