advent_of_code::solution!(9); type Seq = Vec; fn all_zero(s: &Seq) -> bool { s.iter().find(|t| **t != 0).is_none() } fn parse(input: &str) -> Vec { input .lines() .filter_map(|line| { if !line.is_empty() { let nums = line.split(" ").map(|n| n.parse::().unwrap()).collect(); Some(nums) } else { None } }) .collect() } fn get_diffs(s: &Seq) -> Seq { let mut result: Seq = vec![]; for index in 0..(s.len() - 1) { result.push(s[index + 1] - s[index]); } result } fn next_number(s: &Seq) -> i32 { if all_zero(s) { 0 } else { let d = get_diffs(s); s.last().unwrap() + next_number(&d) } } pub fn part_one(input: &str) -> Option { Some( parse(input) .iter() .map(|s| next_number(&s)) .sum::() .try_into() .unwrap(), ) } fn previous_number(s: &Seq) -> i32 { if all_zero(s) { 0 } else { let d = get_diffs(s); s[0] - previous_number(&d) } } pub fn part_two(input: &str) -> Option { Some( parse(input) .iter() .map(|s| previous_number(&s)) .sum::() .try_into() .unwrap(), ) } #[cfg(test)] mod tests { use super::*; #[test] fn test_part_one() { let result = part_one(&advent_of_code::template::read_file("examples", DAY)); assert_eq!(result, Some(114)); } #[test] fn test_part_two() { let result = part_two(&advent_of_code::template::read_file("examples", DAY)); assert_eq!(result, Some(2)); } }