1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#![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<std::cmp::Ordering> {
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::<usize>().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::<u32>().unwrap()).sum())
.collect::<Vec<u32>>();
cals.sort_unstable();
println!("{}", cals.into_iter().rev().take(3).sum::<u32>());
}
|