#![allow(clippy::needless_range_loop)] #![forbid(elided_lifetimes_in_paths, unsafe_code)] use aoc23::read; use chumsky::prelude::*; struct History(Vec); impl History { fn parser() -> impl Parser> { one_of(['-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) .repeated() .at_least(1) .separated_by(just(" ")) .map(|nums: Vec>| { Self( nums.into_iter() .map(|num| num.into_iter().collect::().parse().unwrap()) .collect() ) }) } } fn parser() -> impl Parser, Error = Simple> { History::parser() .then_ignore(just("\n")) .repeated() .then_ignore(end()) } impl History { fn diff(&self) -> Self { let mut diffs = Vec::with_capacity(self.0.len() - 1); 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_last(&self) -> i64 { if self.0.iter().any(|num| *num != 0) { let diff = self.diff(); let last = diff.extend_last(); self.0.last().unwrap() + last } else { 0 } } fn extend_first(&self) -> i64 { if self.0.iter().any(|num| *num != 0) { let diff = self.diff(); let first = diff.extend_first(); self.0.first().unwrap() - first } else { 0 } } } fn main() -> anyhow::Result<()> { let histories = read("inputs/day9.txt", parser())?; let mut sum_last = 0; let mut sum_first = 0; for h in histories { sum_last += h.extend_last(); sum_first += h.extend_first(); } println!("{sum_last}"); println!("{sum_first}"); Ok(()) }