67 lines
1.4 KiB
Rust
67 lines
1.4 KiB
Rust
|
#![allow(clippy::needless_range_loop)]
|
||
|
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
||
|
|
||
|
use aoc23::read;
|
||
|
use chumsky::{prelude::*, text::int};
|
||
|
|
||
|
struct History(Vec<i64>);
|
||
|
|
||
|
impl History {
|
||
|
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
|
||
|
one_of(['-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])
|
||
|
.repeated()
|
||
|
.at_least(1)
|
||
|
.separated_by(just(" "))
|
||
|
.map(|nums: Vec<Vec<char>>| {
|
||
|
Self(
|
||
|
nums.into_iter()
|
||
|
.map(|num| num.into_iter().collect::<String>().parse().unwrap())
|
||
|
.collect()
|
||
|
)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn parser() -> impl Parser<char, Vec<History>, Error = Simple<char>> {
|
||
|
History::parser()
|
||
|
.then_ignore(just("\n"))
|
||
|
.repeated()
|
||
|
.then_ignore(end())
|
||
|
}
|
||
|
|
||
|
impl History {
|
||
|
fn diff(&self) -> Self {
|
||
|
// intentionally reserve one space extra for .extend()
|
||
|
let mut diffs = Vec::with_capacity(self.0.len());
|
||
|
if self.0.len() > 1 {
|
||
|
for i in 1 .. self.0.len() {
|
||
|
diffs.push(self.0[i] - self.0[i - 1]);
|
||
|
}
|
||
|
}
|
||
|
Self(diffs)
|
||
|
}
|
||
|
|
||
|
fn extend(&mut self) {
|
||
|
if self.0.iter().any(|num| *num != 0) {
|
||
|
let mut diff = self.diff();
|
||
|
diff.extend();
|
||
|
self.0.push(self.0.last().unwrap() + diff.0.last().unwrap());
|
||
|
} else {
|
||
|
self.0.push(0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn main() -> anyhow::Result<()> {
|
||
|
let histories = read("inputs/day9.txt", parser())?;
|
||
|
|
||
|
let mut sum = 0;
|
||
|
for mut h in histories {
|
||
|
h.extend();
|
||
|
sum += h.0.last().unwrap();
|
||
|
}
|
||
|
println!("{sum}");
|
||
|
|
||
|
Ok(())
|
||
|
}
|