AoC23/src/day09.rs

66 lines
1.6 KiB
Rust

pub fn run() {
let input = include_str!("../input/day9.txt");
// let input = r#"0 3 6 9 12 15
// 1 3 6 10 15 21
// 10 13 16 21 30 45"#;
let sequences = input.lines().map(parse_sequence).collect::<Vec<_>>();
dbg!(sequences.iter().map(|s| extrapolate(&s)).sum::<i32>());
dbg!(sequences.iter().map(|s| extrapolate_back(&s)).sum::<i32>());
}
fn parse_sequence(s: &str) -> Vec<i32> {
s.trim().split(" ").map(|s| s.parse().unwrap()).collect()
}
fn extrapolate(seq: &[i32]) -> i32 {
let deltas = deltas(seq);
if deltas.iter().all(|x| *x == 0) {
*seq.last().unwrap()
} else {
let next_delta = extrapolate(&deltas);
*seq.last().unwrap() + next_delta
}
}
fn extrapolate_back(seq: &[i32]) -> i32 {
let deltas = deltas(seq);
if deltas.iter().all(|x| *x == 0) {
seq[0]
} else {
let prev_delta = extrapolate_back(&deltas);
seq[0] - prev_delta
}
}
fn deltas(seq: &[i32]) -> Vec<i32> {
seq.iter()
.zip(seq.iter().skip(1))
.map(|(a, b)| b - a)
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deltas() {
assert_eq!(deltas(&[1, 2, 3]), vec![1, 1]);
assert_eq!(deltas(&[1, 1, 1]), vec![0, 0]);
}
#[test]
fn test_extrapolate() {
assert_eq!(extrapolate(&[1, 1, 1]), 1);
assert_eq!(extrapolate(&[1, 2, 3]), 4);
assert_eq!(extrapolate(&[1, 3, 6]), 10);
}
#[test]
fn test_extrapolate_back() {
assert_eq!(extrapolate_back(&[10, 13, 16, 21, 30, 45]), 5);
}
}