diff --git a/2022/day-10/src/bin/part_one.rs b/2022/day-10/src/bin/part_one.rs index 7992131..9b56587 100644 --- a/2022/day-10/src/bin/part_one.rs +++ b/2022/day-10/src/bin/part_one.rs @@ -1,6 +1,6 @@ use std::{env, io}; -use aoc_2022_10::{parse_input, Instruction}; +use aoc_2022_10::Device; fn main() -> io::Result<()> { let infile_path = env::args().nth(1).expect("input file"); @@ -13,33 +13,26 @@ fn main() -> io::Result<()> { } fn solve(path: &str) -> io::Result { - let instructions = parse_input(path)?; + let mut device = Device::initialize(path)?; - let mut cycles_total: i64 = 0; - let mut reg_x: i64 = 1; let mut sig_strength_total: i64 = 0; - for instruction in instructions { - let (cycles, add_x) = match instruction { - Instruction::Noop => (1, 0), - Instruction::Addx(val) => (2, val), - }; - - for _ in 0..cycles { - cycles_total += 1; - - if cycles_total == 20 || (cycles_total - 20) % 40 == 0 { - let sig_strength = cycles_total * reg_x; - sig_strength_total += sig_strength; - } - } - - reg_x += add_x; - } + device.for_each_cycle(|cycles_total, reg_x| { + compute_cycle(reg_x, cycles_total, &mut sig_strength_total); + }); Ok(sig_strength_total) } +fn compute_cycle(reg_x: i64, cycles_total: &mut i64, sig_strength_total: &mut i64) { + *cycles_total += 1; + + if *cycles_total == 20 || (*cycles_total - 20) % 40 == 0 { + let sig_strength = *cycles_total * reg_x; + *sig_strength_total += sig_strength; + } +} + #[cfg(test)] mod test { use super::*; diff --git a/2022/day-10/src/bin/part_two.rs b/2022/day-10/src/bin/part_two.rs index ffbedfa..72d5e9f 100644 --- a/2022/day-10/src/bin/part_two.rs +++ b/2022/day-10/src/bin/part_two.rs @@ -1,6 +1,6 @@ use std::{env, io}; -use aoc_2022_10::{parse_input, Instruction}; +use aoc_2022_10::Device; fn main() -> io::Result<()> { let infile_path = env::args().nth(1).expect("input file"); @@ -12,42 +12,22 @@ fn main() -> io::Result<()> { Ok(()) } +type CrtRow = [char; 40]; +type Crt = Vec; + const PIXEL_LIT: char = '#'; const PIXEL_UNLIT: char = '.'; const DRAW_CYCLE: i64 = 40; fn solve(path: &str) -> io::Result { - let instructions = parse_input(path)?; + let mut device = Device::initialize(path)?; - let mut crt = Vec::<[char; 40]>::new(); + let mut crt = Crt::new(); let mut crt_row = [PIXEL_UNLIT; 40]; - let mut cycles_total: i64 = 0; - let mut reg_x: i64 = 1; - - for instruction in instructions { - let (cycles, add_x) = match instruction { - Instruction::Noop => (1, 0), - Instruction::Addx(val) => (2, val), - }; - - for _ in 0..cycles { - let cur_row_pos = cycles_total % DRAW_CYCLE; - - if ((reg_x - 1)..=(reg_x + 1)).contains(&cur_row_pos) { - crt_row[cur_row_pos as usize] = PIXEL_LIT; - } - - cycles_total += 1; - - if cycles_total % DRAW_CYCLE == 0 { - crt.push(crt_row); - crt_row = [PIXEL_UNLIT; 40]; - } - } - - reg_x += add_x; - } + device.for_each_cycle(|cycles_total, reg_x| { + compute_cycle(reg_x, cycles_total, &mut crt, &mut crt_row); + }); let lines = crt .iter() @@ -58,6 +38,22 @@ fn solve(path: &str) -> io::Result { Ok(lines) } +fn compute_cycle(reg_x: i64, cycles_total: &mut i64, crt: &mut Crt, crt_row: &mut CrtRow) { + let cur_row_pos = *cycles_total % DRAW_CYCLE; + let sprite_area = (reg_x - 1)..=(reg_x + 1); + + if sprite_area.contains(&cur_row_pos) { + crt_row[cur_row_pos as usize] = PIXEL_LIT; + } + + *cycles_total += 1; + + if *cycles_total % DRAW_CYCLE == 0 { + crt.push(*crt_row); + *crt_row = [PIXEL_UNLIT; 40]; + } +} + #[cfg(test)] mod test { use super::*; diff --git a/2022/day-10/src/lib.rs b/2022/day-10/src/lib.rs index 2099a7e..42a3e37 100644 --- a/2022/day-10/src/lib.rs +++ b/2022/day-10/src/lib.rs @@ -4,12 +4,60 @@ use std::{ path::Path, }; -pub enum Instruction { +pub struct Device { + instructions: Vec, + cycles_total: i64, + reg_x: i64, +} + +impl Device { + pub fn initialize

(path: P) -> io::Result + where + P: AsRef, + { + let instructions = parse_input(path)?; + Ok(Self { + instructions, + cycles_total: 0, + reg_x: 1, + }) + } + + pub fn for_each_cycle(&mut self, mut cycle_fn: F) + where + F: FnMut(&mut i64, i64), + { + for instruction in &self.instructions { + for _ in 0..instruction.cycles() { + cycle_fn(&mut self.cycles_total, self.reg_x); + } + self.reg_x += instruction.value(); + } + } +} + +enum Instruction { Noop, Addx(i64), } -pub fn parse_input

(path: P) -> io::Result> +impl Instruction { + pub fn cycles(&self) -> i64 { + match self { + Self::Noop => 1, + Self::Addx(_) => 2, + } + } + + pub fn value(&self) -> i64 { + match self { + Self::Noop => 0, + Self::Addx(val) => *val, + } + } +} + +fn parse_input

(path: P) -> io::Result> where P: AsRef, {