Update solution for 2022 day 10
Overengineer the solution just for fun
This commit is contained in:
parent
02f92114d3
commit
c173b62d37
@ -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<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;
|
||||
|
||||
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::*;
|
||||
|
@ -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<CrtRow>;
|
||||
|
||||
const PIXEL_LIT: char = '#';
|
||||
const PIXEL_UNLIT: char = '.';
|
||||
const DRAW_CYCLE: i64 = 40;
|
||||
|
||||
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 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<String> {
|
||||
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::*;
|
||||
|
@ -4,12 +4,60 @@ use std::{
|
||||
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,
|
||||
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
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user