use anyhow::Result; use std::collections::HashMap; use std::env::args; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::Path; fn read_input>(filename: T) -> Result> { let f = File::open(filename)?; let reader = BufReader::new(f); let values = reader.lines() .map(|v| v?.parse::().map_err(anyhow::Error::new)).collect(); values } fn part1(input: &[usize]) -> Option { let mut sorted = input.to_vec(); sorted.push(0); sorted.sort(); let max = sorted[sorted.len()-1]; sorted.push(max+3); let (_prev, count) = sorted.iter().fold((None, vec![0, 0, 0, 0]), |acc, jolt| { let mut res = acc.1.clone(); if let Some(prev) = acc.0 { let diff = jolt - prev; res[diff] += 1; } (Some(jolt), res) }); Some(count[1] * count[3]) } fn part2(input: &[usize]) -> Option { let mut sorted = input.to_vec(); sorted.push(0); sorted.sort(); let max = sorted[sorted.len()-1]; sorted.push(max+3); let mut paths: HashMap = HashMap::new(); paths.insert(max+3, 1); sorted.iter().rev().fold(0, |_, elem| { let count = (1..=3).map(|jump| { let pos = *elem + jump; if sorted.contains(&pos) { paths.get(&pos).copied().unwrap_or(0) } else { 0 } }).sum(); let lm = paths.entry(*elem).or_insert(0); *lm += count; count }); Some(paths[&0]) } fn main() { let ( do_part_1, do_part_2 ) = aoc::do_parts(); let filename = match args().nth(1) { Some(f) => f, None => { eprintln!("Missing input filename"); std::process::exit(1); }, }; match read_input(filename) { Ok(input) => { if do_part_1 { match part1(&input) { Some(solution) => println!("Part1: {}", solution), None => { eprintln!("Part1, no solution found"); std::process::exit(1); } }; } if do_part_2 { match part2(&input) { Some(solution) => println!("Part2: {}", solution), None => { eprintln!("Part2, no solution found"); std::process::exit(1); } }; } }, Err(err) => eprintln!("Could not read input: {}", err), } }