use { anyhow::{ anyhow, Context, Result, }, std::{ env::args, fs::File, io::{ BufRead, BufReader, }, path::Path, }, }; fn read_input>(filename: T) -> Result> { let reader = BufReader::new(File::open(filename)?); reader.lines().map( |v| v?.parse().map_err(|err| anyhow!("Could not parse input: {}", err)) ).collect() } #[derive(PartialEq)] enum Change { NoPrevVal, Increased, Decreased, Identical, } fn count_increases<'a, I: IntoIterator>(values: I) -> usize { let changes: Vec = values.into_iter().scan(None, |state, val| { let next = match state { None => Change::NoPrevVal, Some(prev) if val < *prev => Change::Decreased, Some(prev) if val > *prev => Change::Increased, Some(prev) if val == *prev => Change::Identical, Some(_) => unreachable!(), }; *state = Some(val); Some(next) }).collect(); changes.iter().fold(0, |count, change| if *change == Change::Increased { count + 1 } else { count } ) } fn part1<'a, I: IntoIterator>(input: I) -> Result { let count = count_increases(input); Ok(count) } fn part2<'a, I: IntoIterator + Copy>(input: I) -> Result { let left_iter = input.into_iter(); let middle_iter = input.into_iter().skip(1); let right_iter = input.into_iter().skip(2); let slidesums: Vec<_> = left_iter.zip(middle_iter).zip(right_iter).map(|n| { let ((first, second), third) = n; first + second + third }).collect(); let count = count_increases(&slidesums); Ok(count) } fn main() -> Result<()> { let ( do_part_1, do_part_2 ) = aoc::do_parts(); let filename = args().nth(1).ok_or(anyhow!("Missing input filename"))?; let input = read_input(filename).context("Could not read input")?; if do_part_1 { let solution = part1(&input).context("No solution for part 1")?; println!("Part1, number of increases found to be: {}", solution); } if do_part_2 { let solution = part2(&input).context("No solution for part 2")?; println!("Part2, number of increases found to be: {}", solution); } Ok(()) }