summaryrefslogtreecommitdiffstats
path: root/day01b/src/main.rs
blob: 4c880c4f35a435efe54c90a75449b6424d27fa37 (plain)
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>());
}