#![feature(binary_heap_into_iter_sorted)] /// --- Part Two --- /// /// By the time you calculate the answer to the Elves' question, they've already realized that the /// Elf carrying the most Calories of food might eventually run out of snacks. /// /// To avoid this unacceptable situation, the Elves would instead like to know the total Calories /// carried by the top three Elves carrying the most Calories. That way, even if one of those Elves /// runs out of snacks, they still have two backups. /// /// In the example above, the top three Elves are the fourth Elf (with 24000 Calories), then the /// third Elf (with 11000 Calories), then the fifth Elf (with 10000 Calories). The sum of the /// Calories carried by these three elves is 45000. /// /// Find the top three Elves carrying the most Calories. How many Calories are those Elves carrying /// in total? use clap::Parser; use std::collections::BinaryHeap; use std::fs::File; use std::io::prelude::*; use std::io::BufReader; use std::path::PathBuf; const FILEPATH: &'static str = "examples/input.txt"; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct Cli { #[clap(short, long, default_value = FILEPATH)] file: PathBuf, } #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] struct CalorieCount { elf: usize, calories: usize, } impl PartialOrd for CalorieCount { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for CalorieCount { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.calories.cmp(&other.calories) } } fn main() { let args = Cli::parse(); let file = File::open(&args.file).unwrap(); let mut reader = BufReader::new(file); let mut heap = BinaryHeap::new(); let mut line = String::new(); let mut calorie_count = CalorieCount { elf: 1, calories: 0, }; while let Ok(bytes) = reader.read_line(&mut line) { // EOF if bytes == 0 { heap.push(calorie_count); break; } // Newlines let tline = line.trim(); if tline.is_empty() { // Push onto the binary heap heap.push(calorie_count); calorie_count.calories = 0; calorie_count.elf += 1; continue; } // Parse the calories let calories = tline.parse::().unwrap(); // Accumulate the calorie count for this elf calorie_count.calories += calories; // Clear the line for the next iteration line.clear(); } // Find the elf carrying the most calories let res = heap .into_iter_sorted() .inspect(|x| println!("calories={:6} elf={}", x.calories, x.elf)) .take(3) .fold(0usize, |acc, x| acc + x.calories); println!("The top 3 elves are carry {res} calories"); let mut cals = include_str!("../examples/input.txt") .split("\n\n") .map(|e| e.lines().map(|c| c.parse::().unwrap()).sum()) .collect::>(); cals.sort_unstable(); println!("{}", cals.into_iter().rev().take(3).sum::()); }