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)?); let mut elves = vec![vec![]]; for line in reader.lines() { let s = line?; if s.is_empty() { elves.push(vec![]); continue; } let elf = elves.last_mut().context("Invalid elves vector.")?; let n = s.parse().context("Could not parse {s}")?; elf.push(n); } Ok(elves) } fn part1<'a, I: IntoIterator>>(input: I) -> Result { input.into_iter().map(|foodpacks| foodpacks.iter().sum()).max() .context("Iterator chain in first part failed.") } fn part2<'a, I: IntoIterator>>(input: I) -> Result { let mut calories: Vec = input.into_iter().map(|foodpacks| foodpacks.iter().sum()) .collect(); calories.sort(); Ok(calories.into_iter().rev().take(3).sum::()) } fn main() -> Result<()> { let ( do_part_1, do_part_2 ) = aoc::do_parts(); let filename = args().nth(1).ok_or_else(|| 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, solution found to be: {}", solution); } if do_part_2 { let solution = part2(&input).context("No solution for part 2")?; println!("Part2, solution found to be: {}", solution); } Ok(()) }