1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
use crate::input::Input; use std::collections::HashSet; type Frequency = i32; fn parse_frequency_changes( input_string: &str, ) -> impl Iterator<Item = Result<Frequency, String>> + Clone + '_ { input_string.lines().enumerate().map(|(line_index, line)| { line.parse::<Frequency>().map_err(|error| { format!( "Invalid input on line {}: {}", line_index + 1, error.to_string() ) }) }) } pub fn solve(input: &mut Input) -> Result<Frequency, String> { const MAX_ITERATIONS: usize = 1_000_000; let change_iterator = parse_frequency_changes(input.text); if input.is_part_one() { change_iterator.sum::<Result<_, _>>() } else { let mut frequency: Frequency = 0; let mut seen_frequencies = HashSet::new(); for change in change_iterator.cycle().take(MAX_ITERATIONS) { if seen_frequencies.insert(frequency) { frequency = frequency.checked_add(change?).ok_or("Too high frequency")?; } else { return Ok(frequency); } } Err(format!( "Frequency not repeated after {} iterations", MAX_ITERATIONS )) } } #[test] pub fn test() { use crate::{test_part_one, test_part_two}; test_part_one!("+1\n-2\n+3\n+1" => 3); test_part_one!("+1\n+1\n+1" => 3); test_part_one!("+1\n+1\n-2" => 0); test_part_one!("-1\n-2\n-3" => -6); test_part_two!("+1\n-1" => 0); test_part_two!("+3\n+3\n+4\n-2\n-4" => 10); test_part_two!("-6\n+3\n+8\n+5\n-6" => 5); test_part_two!("+7\n+7\n-2\n-7\n-4" => 14); let real_input = include_str!("day01_input.txt"); test_part_one!(real_input => 477); test_part_two!(real_input => 390); }