2022 day10/rust: use generators

This commit is contained in:
Xiretza 2022-12-10 09:42:00 +01:00
parent 135a5017f7
commit 0618083106

View file

@ -1,3 +1,6 @@
#![feature(generators)]
#![feature(generator_clone)]
#![feature(iter_from_generator)]
#![warn(clippy::pedantic)] #![warn(clippy::pedantic)]
use std::{ use std::{
@ -6,9 +9,48 @@ use std::{
str::FromStr, str::FromStr,
}; };
type Word = i64;
#[derive(Debug, Clone, PartialEq, Eq)]
struct MachineState {
x: Word,
}
impl MachineState {
const fn new() -> Self {
Self { x: 1 }
}
fn execute(&mut self, op: MicroOp) {
match op {
MicroOp::Noop => {}
MicroOp::Addx(i) => self.x += i,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MicroOp {
Noop,
Addx(Word),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Instruction { enum Instruction {
Noop, Noop,
Addx(i32), Addx(Word),
}
impl Instruction {
pub fn expand(self) -> impl Iterator<Item = MicroOp> {
iter::from_generator(move || match self {
Self::Noop => yield MicroOp::Noop,
Self::Addx(x) => {
yield MicroOp::Noop;
yield MicroOp::Addx(x);
}
})
}
} }
impl FromStr for Instruction { impl FromStr for Instruction {
@ -28,35 +70,35 @@ impl FromStr for Instruction {
} }
fn main() { fn main() {
const START: MachineState = MachineState::new();
let mut data = String::new(); let mut data = String::new();
stdin().read_to_string(&mut data).unwrap(); stdin().read_to_string(&mut data).unwrap();
let values = data let states: Vec<_> = data
.lines() .lines()
.map(|l| l.parse().unwrap()) .map(|l| l.parse().unwrap())
.flat_map(|i: Instruction| match i { .flat_map(Instruction::expand)
Instruction::Noop => vec![0], .scan(START, |state, op| {
Instruction::Addx(i) => vec![0, i], let prev = state.clone();
state.execute(op);
Some(prev)
}) })
.scan(1, |acc, i| {
*acc += i;
Some(*acc)
});
let values = iter::once(1)
.chain(values)
.enumerate() .enumerate()
.map(|(i, x)| (i32::try_from(i).unwrap() + 1, x)); .map(|(i, state)| (Word::try_from(i).unwrap() + 1, state))
.collect();
let sum: i32 = values let sum: Word = states
.clone() .iter()
.skip(20 - 1) .skip(20 - 1)
.step_by(40) .step_by(40)
.map(|(i, x)| i * x) .map(|(i, state)| i * state.x)
.sum(); .sum();
println!("{:?}", sum); println!("{:?}", sum);
let crt: Vec<_> = values let crt: Vec<_> = states
.map(|(i, x)| ((i - 1) % 40).abs_diff(x) < 2) .iter()
.map(|(i, state)| ((i - 1) % 40).abs_diff(state.x) < 2)
.map(|x| if x { '#' } else { '.' }) .map(|x| if x { '#' } else { '.' })
.collect(); .collect();