From de440ef10e0f7c53d6176b5dfdba07b9ccf95e21 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 9 Dec 2023 10:52:23 +0100 Subject: [PATCH] Implement 2023 day 9 --- 2023/src/day09.rs | 80 ++++++++++++++++++++++++++++++++++++++--- 2023/src/samples/09.txt | 3 ++ 2 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 2023/src/samples/09.txt diff --git a/2023/src/day09.rs b/2023/src/day09.rs index 7c1760f..4742663 100644 --- a/2023/src/day09.rs +++ b/2023/src/day09.rs @@ -1,7 +1,79 @@ -pub fn part1(_input: &[u8]) -> anyhow::Result { - anyhow::bail!("Not implemented") +use std::mem; + +use nom::bytes::complete::tag; +use nom::multi::many1; +use nom::multi::separated_list1; +use nom::sequence::terminated; +use nom::IResult; + +use crate::common::parse_input; + +fn parse_reports(i: &[u8]) -> IResult<&[u8], Vec>> { + many1(terminated( + separated_list1(tag(" "), nom::character::complete::i32), + tag("\n"), + ))(i) } -pub fn part2(_input: &[u8]) -> anyhow::Result { - anyhow::bail!("Not implemented") +fn compute_next(report: &[i32]) -> i32 { + let mut deltas = Vec::new(); + + for w in report.windows(2) { + let mut delta = w[1] - w[0]; + + for prev_delta in &mut deltas { + let prev = mem::replace(prev_delta, delta); + delta = delta - prev; + } + + if delta != 0 { + deltas.push(delta); + } + } + + let next_step = deltas.drain(..).rev().fold(0, |c, d| c + d); + + report.last().unwrap() + next_step +} + +pub fn part1(input: &[u8]) -> anyhow::Result { + let reports = parse_input(input, parse_reports)?; + let result: i32 = reports.iter().map(|report| compute_next(&report)).sum(); + Ok(result.to_string()) +} + +pub fn part2(input: &[u8]) -> anyhow::Result { + let mut reports = parse_input(input, parse_reports)?; + let result: i32 = reports + .iter_mut() + .map(|report| { + report.reverse(); + compute_next(&report) + }) + .sum(); + Ok(result.to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const SAMPLE: &[u8] = include_bytes!("samples/09.txt"); + + #[test] + fn samples_separate() { + assert_eq!(18, compute_next(&[0, 3, 6, 9, 12, 15])); + assert_eq!(28, compute_next(&[1, 3, 6, 10, 15, 21])); + assert_eq!(68, compute_next(&[10, 13, 16, 21, 30, 45])); + } + + #[test] + fn sample_part1() { + assert_eq!("114", part1(SAMPLE).unwrap()); + } + + #[test] + fn sample_part2() { + assert_eq!("2", part2(SAMPLE).unwrap()); + } } diff --git a/2023/src/samples/09.txt b/2023/src/samples/09.txt new file mode 100644 index 0000000..539a763 --- /dev/null +++ b/2023/src/samples/09.txt @@ -0,0 +1,3 @@ +0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45