Update solution for 2022 day 10

Overengineer the solution just for fun
This commit is contained in:
Patrick Auernig 2022-12-11 16:36:09 +01:00
parent 02f92114d3
commit c173b62d37
3 changed files with 89 additions and 52 deletions

View File

@ -1,6 +1,6 @@
use std::{env, io}; use std::{env, io};
use aoc_2022_10::{parse_input, Instruction}; use aoc_2022_10::Device;
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let infile_path = env::args().nth(1).expect("input file"); let infile_path = env::args().nth(1).expect("input file");
@ -13,33 +13,26 @@ fn main() -> io::Result<()> {
} }
fn solve(path: &str) -> io::Result<i64> { fn solve(path: &str) -> io::Result<i64> {
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; let mut sig_strength_total: i64 = 0;
for instruction in instructions { device.for_each_cycle(|cycles_total, reg_x| {
let (cycles, add_x) = match instruction { compute_cycle(reg_x, cycles_total, &mut sig_strength_total);
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;
}
Ok(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)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View File

@ -1,6 +1,6 @@
use std::{env, io}; use std::{env, io};
use aoc_2022_10::{parse_input, Instruction}; use aoc_2022_10::Device;
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let infile_path = env::args().nth(1).expect("input file"); let infile_path = env::args().nth(1).expect("input file");
@ -12,42 +12,22 @@ fn main() -> io::Result<()> {
Ok(()) Ok(())
} }
type CrtRow = [char; 40];
type Crt = Vec<CrtRow>;
const PIXEL_LIT: char = '#'; const PIXEL_LIT: char = '#';
const PIXEL_UNLIT: char = '.'; const PIXEL_UNLIT: char = '.';
const DRAW_CYCLE: i64 = 40; const DRAW_CYCLE: i64 = 40;
fn solve(path: &str) -> io::Result<String> { fn solve(path: &str) -> io::Result<String> {
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 crt_row = [PIXEL_UNLIT; 40];
let mut cycles_total: i64 = 0; device.for_each_cycle(|cycles_total, reg_x| {
let mut reg_x: i64 = 1; compute_cycle(reg_x, cycles_total, &mut crt, &mut crt_row);
});
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;
}
let lines = crt let lines = crt
.iter() .iter()
@ -58,6 +38,22 @@ fn solve(path: &str) -> io::Result<String> {
Ok(lines) 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)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View File

@ -4,12 +4,60 @@ use std::{
path::Path, path::Path,
}; };
pub enum Instruction { pub struct Device {
instructions: Vec<Instruction>,
cycles_total: i64,
reg_x: i64,
}
impl Device {
pub fn initialize<P>(path: P) -> io::Result<Self>
where
P: AsRef<Path>,
{
let instructions = parse_input(path)?;
Ok(Self {
instructions,
cycles_total: 0,
reg_x: 1,
})
}
pub fn for_each_cycle<F>(&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, Noop,
Addx(i64), Addx(i64),
} }
pub fn parse_input<P>(path: P) -> io::Result<Vec<Instruction>> 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<P>(path: P) -> io::Result<Vec<Instruction>>
where where
P: AsRef<Path>, P: AsRef<Path>,
{ {