aboutsummaryrefslogtreecommitdiff
path: root/2022/src/day10.rs
blob: 4c7444461bcc3b5c94e72c394c8b960d51c7a923 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
mod utils;
use utils::{parse_num, parse_static, read_input};

fn main() {
    let input = read_input();

    let mut cmds = input.lines().map(parse_cmd);
    let mut state = State {
        x: 1,
        add_next: None,
        add_next_start: None,
        crt_pos: 0,
    };

    let mut acc = 0;
    run_steps::<20>(&mut state, &mut cmds);
    acc += state.x * 20;
    for i in 1..=5 {
        run_steps::<40>(&mut state, &mut cmds);
        acc += state.x * (20 + (i * 40));
    }

    run_steps::<{ TOTAL_STEPS - 220 }>(&mut state, &mut cmds);

    println!("Part 1: {}", acc);
}

struct State {
    x: isize,
    add_next: Option<isize>,
    add_next_start: Option<isize>,
    crt_pos: usize,
}

const CRT_WIDTH: usize = 40;
const CRT_HEIGHT: usize = 6;
const TOTAL_STEPS: usize = CRT_WIDTH * CRT_HEIGHT;

fn run_steps<const N: usize>(state: &mut State, cmd: &mut impl Iterator<Item = Command>) {
    for _ in 0..N {
        if let Some(add) = state.add_next_start.take() {
            state.x += add;
        }

        if (state.x - (state.crt_pos % CRT_WIDTH) as isize).abs() < 2 {
            print!("█");
        } else {
            print!(" ");
        }
        state.crt_pos += 1;
        if (state.crt_pos % CRT_WIDTH) == 0 {
            println!();
        }

        if let Some(add) = state.add_next.take() {
            state.add_next_start = Some(add);
        } else {
            match cmd.next() {
                Some(Command::NoOp) => (),
                Some(Command::AddX(add)) => state.add_next = Some(add),
                None => (),
            }
        }
    }
}

fn parse_cmd(cmd: &str) -> Command {
    if cmd == "noop" {
        Command::NoOp
    } else {
        let cmd = parse_static("addx ", cmd);
        let (add, _) = parse_num(cmd);

        Command::AddX(add)
    }
}

#[derive(Debug)]
enum Command {
    NoOp,
    AddX(isize),
}