diff --git a/src/bin/day10.rs b/src/bin/day10.rs index 63de3b3..8276f99 100644 --- a/src/bin/day10.rs +++ b/src/bin/day10.rs @@ -1,13 +1,12 @@ -use std::str::FromStr; +use std::{fmt::Display, str::FromStr}; use aoc_2022::*; use color_eyre::{eyre::eyre, Report}; use itertools::Itertools; -use tracing::{debug, info}; type Input = Vec; -type Output = i32; +type Output = Out; #[derive(Debug)] enum Instruction { @@ -32,6 +31,35 @@ impl FromStr for Instruction { } } +#[derive(Debug, PartialEq, Eq)] +enum Out { + Strengths(i32), + Screen(Vec>), +} + +impl Out { + fn new_strengths() -> Out { + Out::Strengths(0) + } + + fn new_screen() -> Out { + Out::Screen(vec![vec![]]) + } +} + +impl Display for Out { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Out::Screen(screen) => write!( + f, + "\n{}", + screen.iter().map(|line| line.iter().join("")).join("\n") + ), + Out::Strengths(strengths) => write!(f, "{strengths}"), + } + } +} + struct State { cycle: i32, register: i32, @@ -45,21 +73,9 @@ impl State { } } - fn execute(&self, i: &Instruction) -> (State, i32) { - let next = match i { - Instruction::Addx(value) => State { - cycle: self.cycle + 2, - register: self.register + value, - }, - Instruction::Noop => State { - cycle: self.cycle + 1, - register: self.register, - }, - }; - // debug!("New state of CPU: cycle={}, register={}", next.cycle, next.register); - - let strength = if let Some(cycle) = - (self.cycle..next.cycle).find(|&c| c >= 20 && (c + 20) % 40 == 0) + fn check_signal_strength(&self, next_cycle: i32, total: &mut i32) { + *total += if let Some(cycle) = + (self.cycle..next_cycle).find(|&c| c >= 20 && (c + 20) % 40 == 0) { // debug!( // "Adding {} x {} = {} to sum", @@ -72,11 +88,27 @@ impl State { } else { 0 }; - - (next, strength) } - fn execute_and_draw(&self, i: &Instruction, screen: &mut Vec>) -> State { + fn draw_crt(&self, next_cycle: i32, screen: &mut Vec>) { + // debug!("Checking: {:?} {:?}", i, (self.cycle..next.cycle)); + (self.cycle..next_cycle).for_each(|c| { + if screen.is_empty() || screen.last().unwrap().len() == 40 { + screen.push(vec![]); + } + + let idx = screen.len() - 1; + screen[idx].push( + if self.register - 1 <= (c - 1) % 40 && (c - 1) % 40 <= self.register + 1 { + '█' + } else { + ' ' + }, + ); + }); + } + + fn execute(&self, i: &Instruction, output: &mut Out) -> State { let next = match i { Instruction::Addx(value) => State { cycle: self.cycle + 2, @@ -89,27 +121,25 @@ impl State { }; // debug!("New state of CPU: cycle={}, register={}", next.cycle, next.register); - // debug!("Checking: {:?} {:?}", i, (self.cycle..next.cycle)); - (self.cycle..next.cycle).for_each(|c| { - let idx = screen.len() - 1; - screen[idx].push( - if self.register - 1 <= (c - 1) % 40 && (c - 1) % 40 <= self.register + 1 { - '█' - } else { - ' ' - }, - ); - // debug!("{} ; {} <= {} <= {}", screen[idx].last().unwrap(), self.register - 1, c % 40, self.register + 1); - - if c % 40 == 0 { - screen.push(Vec::new()); - } - }); + match output { + Out::Screen(screen) => self.draw_crt(next.cycle, screen), + Out::Strengths(strengths) => self.check_signal_strength(next.cycle, strengths), + } next } } +fn evaluate_instructions(instructions: &[Instruction], mut out: Output) -> Output { + instructions + .iter() + .fold(State::new(), |state, instruction| { + state.execute(instruction, &mut out) + }); + + out +} + struct Day10; impl Solution for Day10 { fn parse_input>(pathname: P) -> Input { @@ -117,29 +147,11 @@ impl Solution for Day10 { } fn part_1(input: &Input) -> Output { - input - .iter() - .fold((State::new(), 0), |(state, strength_sum), instruction| { - let (new_state, strength) = state.execute(instruction); - - (new_state, strength_sum + strength) - }) - .1 + evaluate_instructions(input, Out::new_strengths()) } fn part_2(input: &Input) -> Output { - let mut screen: Vec> = vec![vec![]]; - - input.iter().fold(State::new(), |state, instruction| { - state.execute_and_draw(instruction, &mut screen) - }); - - info!( - "Screen:\n{}", - screen.iter().map(|line| line.iter().join("")).join("\n") - ); - - 0 + evaluate_instructions(input, Out::new_screen()) } } @@ -147,4 +159,19 @@ fn main() -> Result<()> { Day10::main() } -test_sample!(day_10, Day10, 13140, 1); +test_sample!( + day_10, + Day10, + Out::Strengths(13140), + Out::Screen( + ("██ ██ ██ ██ ██ ██ ██ ██ ██ ██ \n\ + ███ ███ ███ ███ ███ ███ ███ \n\ + ████ ████ ████ ████ ████ \n\ + █████ █████ █████ █████ \n\ + ██████ ██████ ██████ ████\n\ + ███████ ███████ ███████ ") + .lines() + .map(|l| l.chars().collect_vec()) + .collect_vec() + ) +);