• Home
  • Blog
    • Programming
    • Art
    • Recipes
    • Home Automation
    • Life
    • Friday Faves
    • Books
    • Writing
    • Games
    • Web Accessibility
    • Advent of Code
  • Projects
  • GLSL Shader Art
  • Glitch Art

  • Github
  • Bluesky
  • Mastodon
  • Duolingo
  • LinkedIn
  • RSS
  • Bridgy Fed

mary.codes

Web development, art, and tinkering with fun projects. JavaScript, Python, WebGL, GLSL, Rust, Lua, and whatever else I find interesting at the moment.

Advent of Code 2022, Day 1 -- Calorie Counting

Mary KnizeBlog iconDec 1st, 2022
3 min read

Advent Of Code

Rust solutions to Advent of Code 2022, day 1.

Another December, another Advent of Code!

This year, I'm going to try using Rust as much as possible, but I might fall back to Python or JavaScript at times.

In 2020, I made it 16 days into December before giving up (although I only did write-ups for nine days that year). Last year, I only got through three days using Rust, and didn't write down anything. ☹️

This year's goal is to go beyond my record of 16 days, and to also write a little something about my problem solving process each day.

Full code for Day 1 can be found on Github.

The Day 1 problem can be found at adventofcode.com/2022/day/1

Jump to:

  • Part 1
  • Part 2
  • What I learned

Since day 1 is pretty easy, I'll start off by showing you my completed code, and then I'll break it down:

use std::fs;
use std::collections::BinaryHeap;

fn main() {
    let mut heap = BinaryHeap::new();
    let contents = fs::read_to_string("input.txt").unwrap();
    let arr = contents
        .split("\n\n")
        .collect::<Vec<&str>>();
    for elf in arr {
        let cals: i32 = elf
            .split("\n")
            .map(|val| val.parse::<i32>().unwrap_or(0))
            .sum();
        heap.push(cals);
    }
    println!("{}", heap.peek().unwrap());

    let mut top3 = 0;
    for _ in 0..3 {
        top3 += heap.pop().unwrap();
    }
    println!("{}", top3);
}

Part 1

The way I initially solved part 1, which asks for the highest sum from the list, was to split the input into an array of arrays, as I've done above. Then, I would have a mutable variable that I would update with the maximum sum. I would then print that sum as my answer.

use std::fs;
use std::cmp;

fn main() {
    let contents = fs::read_to_string("input.txt").unwrap();
    let mut maximum = 0;

    // Split by double newlines to create a per-elf vector.
    let arr = contents
        .split("\n\n")
        .collect::<Vec<&str>>();

    // Iterate over each elf's snacks.
    for elf in arr {
        // Split the remaining string by newline, cast to integer, and sum.
        let cals: i32 = elf
            .split("\n")
            .map(|val| val.parse::<i32>().unwrap_or(0))
            .sum();
        // Update the maximum value.
        maximum = cmp::max(maximum, cals);
    }
    println!("{}", maximum);
}

However, after seeing part 2 of the question, I realized that the whole problem could be better solved with a max heap. I've used heapq in Python before, but I've never used a heap in Rust before. Luckily, I found that Rust has BinaryHeap in the standard library. As a bonus, BinaryHeap creates a max heap by default, as opposed to heapq's default min heap.

Rewriting the part 1 to use BinaryHeap looks like this:

use std::fs;
use std::collections::BinaryHeap;

fn main() {
    let mut heap = BinaryHeap::new();
    let contents = fs::read_to_string("input.txt").unwrap();

    // Split by double newlines to create a per-elf vector.
    let arr = contents
        .split("\n\n")
        .collect::<Vec<&str>>();
    // Iterate over each elf's snacks.
    for elf in arr {
        // Split the remaining string by newline, cast to integer, and sum.
        let cals: i32 = elf
            .split("\n")
            .map(|val| val.parse::<i32>().unwrap_or(0))
            .sum();
        // Push the total value to the heap.
        heap.push(cals);
    }

    // Peek at the heap and print the largest value.
    println!("{}", heap.peek().unwrap());
}

Part 2

Since part 2 just asks for a sum of the top three totals, and we already have a max heap, it's trivial to pop the top three amounts off of the heap and add them together. I've added a mutable variable to sum the values, and simply loop three times to pop off the top values.

let mut top3 = 0;
for _ in 0..3 {
    top3 += heap.pop().unwrap();
}
println!("{}", top3);

An earlier iteration had me using:

let top3 = heap
    .into_sorted_vec()
    .rev()
    .iter()
    .take(3)
    .sum()

It seems inefficient. Why use a heap when you're just going to transform it into a vector, reverse it, and then turn it into an iterable? Also, into_sorted_vec returns the items sorted in ascending order, as opposed to the descending order that is the max heap. In that case I would've just pushed each sum to a vector, sorted it, then taken the top three and summed those.

Perhaps there's a better way than using a mutable to hold the running total, but it's in the nightly Rust build.

rustup update
rustup default nightly

Then, at the very top of main.rs, use this flag:

#![feature(binary_heap_into_iter_sorted)]

Now, into_iter_sorted will return an iterable from the heap, that's in descending order, and then I can take the top three items and sum them.

let top3: i32 = heap
    .into_iter_sorted()
    .take(3)
    .sum();
println!("{}", top3);

Quite helpful if you can use experimental methods!

What I learned

  • BinaryHeap - A max heap data structure.
  • Rust nightly - Nightly build of Rust with cutting-edge features.
  • .into_iter_sorted() - A Rust nightly method for BinaryHeap that allows you to turn a heap into a sorted iterable.

Other Advent Of Code posts

Advent of Code 2022, Day 8 -- Treetop Tree House

Advent of Code 2022, Day 7 -- No Space Left On Device

Advent of Code 2022, Day 6 -- Tuning Trouble

Advent of Code 2022, Day 5 -- Supply Stacks

Advent of Code 2022, Day 4 -- Camp Cleanup

Latest posts

I started painting again

100 days of Japanese on Duolingo

How I'm organizing my work in 2024

Watch the documentary 'Good Night Oppy' if you're feeling science-y

Sculpted robo-goldfish, a rainbow office building, and a look inside click farms