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::>(); dbg!(sequences.iter().map(|s| extrapolate(&s)).sum::()); dbg!(sequences.iter().map(|s| extrapolate_back(&s)).sum::()); } fn parse_sequence(s: &str) -> Vec { 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 { 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); } }