diff --git a/src/days/day10.rs b/src/days/day10.rs new file mode 100644 index 0000000..0501fec --- /dev/null +++ b/src/days/day10.rs @@ -0,0 +1,103 @@ +use aoc_runner_derive::{aoc, aoc_generator}; + +#[derive(Debug, Clone, Copy)] +enum Instruction { + AddX(i32), + NoOp, +} + +#[aoc_generator(day10)] +fn generator(input: &str) -> Vec { + input + .lines() + .map(|l| { + if l == "noop" { + Instruction::NoOp + } else if let Some(l) = l.strip_prefix("addx ") { + Instruction::AddX(l.parse().unwrap()) + } else { + panic!() + } + }) + .collect() +} + +struct CpuState { + cycle: i32, + x: i32, +} + +fn run_simulation(input: &[Instruction], mut during_cycle_handler: impl FnMut(CpuState)) { + let mut cycle = 1; + let mut x = 1; + let mut iter = input.iter().copied(); + let mut current_instruction = iter.next().unwrap(); + let mut current_instruction_cycle = 0; + + // god i hate fenceposts + loop { + // START OF CYCLE + + let need_new_instruction = match (current_instruction, current_instruction_cycle) { + (_, 0) => false, + (Instruction::NoOp, 1) => true, + (Instruction::AddX(_), 1) => false, + (Instruction::AddX(v), 2) => { + x += v; + true + } + _ => unreachable!(), + }; + + if need_new_instruction { + let Some(tmp) = iter.next() else { + break + }; + current_instruction = tmp; + current_instruction_cycle = 0; + } + + // DURING CYCLE + + during_cycle_handler(CpuState { cycle, x }); + + // END OF CYCLE + + current_instruction_cycle += 1; + cycle += 1; + } +} + +#[aoc(day10, part1)] +fn part1(input: &[Instruction]) -> i32 { + let mut res = 0; + + run_simulation(input, |CpuState { cycle, x }| { + if (cycle + 20) % 40 == 0 { + res += cycle * x; + } + }); + + res +} + +#[aoc(day10, part2)] +fn part2(input: &[Instruction]) -> String { + let mut res = "\n".to_owned(); // newline so that `cargo aoc` formats this nicely + + run_simulation(input, |CpuState { cycle, x }| { + let crt_x_pos = (cycle - 1) % 40; + + if (crt_x_pos - x).abs() <= 1 { + res.push('#'); + } else { + res.push(' '); // the puzzle says `.` but ` ` is more readable + } + + if cycle % 40 == 0 { + res.push('\n'); + } + }); + + res +} diff --git a/src/lib.rs b/src/lib.rs index 9308850..68fc459 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,8 @@ mod days { mod day7; mod day8; mod day9; + // curse you, rustfmt + mod day10; } aoc_lib! { year = 2022 }