adventofcode23/src/day9.rs
2023-12-09 11:20:19 +01:00

80 lines
1.8 KiB
Rust

//! Day 9: Mirage Maintenance
use itertools::Itertools;
pub const DAY: u8 = 9;
pub const TITLE: &str = "Mirage Maintenance";
fn parse(input: Vec<String>) -> Vec<Vec<i32>> {
input
.iter()
.map(|l| {
l.split_ascii_whitespace()
.map(|n| n.parse().unwrap())
.collect()
})
.collect()
}
fn solve(input: Vec<String>, first: bool) -> String {
let parsed = parse(input);
parsed
.into_iter()
.map(|l| {
let mut sequences: Vec<Vec<i32>> = vec![l];
while !sequences.last().unwrap().iter().all_equal() {
sequences.push(
sequences
.last()
.unwrap()
.iter()
.tuple_windows()
.map(|(a, b)| b - a)
.collect_vec(),
);
}
sequences.iter().rev().fold(0, |acc, s| {
if first {
s.first().unwrap() - acc
} else {
acc + s.last().unwrap()
}
})
})
.sum::<i32>()
.to_string()
}
pub fn part1(input: Vec<String>) -> String {
solve(input, false)
}
pub fn part2(input: Vec<String>) -> String {
solve(input, true)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn t_example1() {
assert_eq!(part1(crate::read_example(DAY, 1)), "114");
}
#[test]
fn t_part1() {
assert_eq!(part1(crate::read_input(DAY)), "1884768153");
}
#[test]
fn t_example2() {
assert_eq!(part2(crate::read_example(DAY, 2)), "2");
}
#[test]
fn t_part2() {
assert_eq!(part2(crate::read_input(DAY)), "1031");
}
}