use std::fs; use std::num::ParseIntError; use itertools::{Itertools, MinMaxResult}; fn main() -> Result<(), Box> { let input = fs::read_to_string("input")?; let xmas = parse_xmas(&input)?; // Part 1 let result = find_not_summed(&xmas, 25)?; println!("{}", result); // Part 2 let result = find_weakness(&xmas, result)?; println!("{}", result); Ok(()) } fn parse_xmas(input: &str) -> Result, ParseIntError> { input.lines().map(|line| line.parse()).collect() } fn find_weakness(xmas: &Vec, key: u64) -> Result { // Now we use the key to find the weakness, by getting all // possible sub-sumbs of the list of numbers, and finding the one // that happens to match our key let weak_window = (2..xmas.len()) .find_map(|window_size| { xmas.windows(window_size) .find(|window| window.iter().sum::() == key) }) .ok_or("Could not find a weakness")?; if let MinMaxResult::MinMax(min, max) = weak_window.iter().minmax() { Ok(min + max) } else { unreachable!("We must have at least two elements due to the window size") } } fn find_not_summed(xmas: &Vec, window_size: usize) -> Result { xmas.windows(window_size + 1) .find_map(|window| { if let [preamble @ .., number] = window { // If none of the number combinations in the preamble // sum to the final number, we've got the key! if !preamble .iter() .combinations(2) .any(|combination| combination.into_iter().sum::() == *number) { Some(*number) } else { None } } else { unreachable!("The windows must all have a length of at least 1"); } }) .ok_or("Could not find the entry") } #[cfg(test)] mod tests { use super::*; use indoc::indoc; #[test] fn test_simple() -> Result<(), Box> { let input = indoc!( "35 20 15 25 47 40 62 55 65 95 102 117 150 182 127 219 299 277 309 576" ); let xmas = parse_xmas(input)?; let result = find_not_summed(&xmas, 5)?; assert_eq!(result, 127); Ok(()) } #[test] fn test_simple2() -> Result<(), Box> { let input = indoc!( "35 20 15 25 47 40 62 55 65 95 102 117 150 182 127 219 299 277 309 576" ); let xmas = parse_xmas(input)?; let key = find_not_summed(&xmas, 5)?; let result = find_weakness(&xmas, key)?; assert_eq!(result, 62); Ok(()) } }