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(values: &[usize]) -> usize { let changes: Vec = values.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(input: &[usize]) -> Result { let count = count_increases(input); Ok(count) } fn part2(input: &[usize]) -> Result { let slidesums: Vec<_> = input.iter().zip(input[1..].iter()).zip(input[2..].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(()) }