1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
use nom::{
bytes::complete::tag,
character::complete::{i32, line_ending},
combinator::map,
multi::{many0, separated_list1},
sequence::{pair, tuple},
IResult,
};
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = fs::read_to_string("inputs/day_10.txt")?;
let program = Program::parser(&input).unwrap().1;
let result = program.process();
dbg!(result.sum_of_signal_strengths(&[20, 60, 100, 140, 180, 220]));
for y in 0..6 {
for x in 0..40 {
if result.pixel_should_activate(x, y) {
print!("#");
} else {
print!(".");
}
}
println!();
}
Ok(())
}
#[derive(Debug)]
struct Program(Vec<TimeSequence>);
#[derive(Debug, Default)]
struct ProgramResult(Vec<TimeSequence>);
#[derive(Debug, Clone)]
struct TimeSequence {
time: u32,
value: i32,
}
impl Program {
fn parser(input: &str) -> IResult<&str, Self> {
map(separated_list1(line_ending, TimeSequence::parser), Program)(input)
}
fn process(&self) -> ProgramResult {
let mut result = ProgramResult::default();
let mut current_state = TimeSequence { time: 1, value: 1 };
result.0.push(current_state.clone());
for next_step in &self.0 {
current_state.time += next_step.time;
current_state.value += next_step.value;
result.0.push(current_state.clone());
}
result
}
}
impl TimeSequence {
fn parser(input: &str) -> IResult<&str, Self> {
map(
tuple((many0(pair(tag("noop"), line_ending)), tag("addx "), i32)),
|(noops, _, value)| TimeSequence {
time: noops.len() as u32 + 2,
value,
},
)(input)
}
}
impl ProgramResult {
fn value_at(&self, time: u32) -> i32 {
self.0
.iter()
.filter(|t| t.time <= time)
.map(|t| t.value)
.last()
.unwrap_or(0)
}
fn signal_strength_at(&self, time: u32) -> i32 {
let value = self.value_at(time);
value * time as i32
}
fn sum_of_signal_strengths(&self, times: &[u32]) -> i32 {
times
.iter()
.map(|time| self.signal_strength_at(*time))
.sum()
}
fn pixel_should_activate(&self, x: usize, y: usize) -> bool {
let time = (y * 40 + x + 1) as u32;
let sprite_middle = self.value_at(time);
((x as i32) - sprite_middle).abs() <= 1
}
}
|