Reaves.dev

v0.1.0

built using

Phoenix v1.7.12

Advent Of Code 2022 - Day One

Stephen M. Reaves

::

2022-12-31

Advent of Code 2022 - Day One

As I’m writing this article, I can tell this is not the most effecient way of doing this, but I’m documenting this anyway because it was the best I could come up with at the time. Let’s take a look at Day One

Part One

Problem

We have a list of numbers separated by blank lines. All the numbers between blank lines represent the calories carried by a particular elf. We need to find which elf carries the most calories. Initially, I misinterpreted this question as finding the sum of all the calories of the elf that has the highest calorie on a single line. Instead, we need to sum all the calories in between the blank lines and keep track of which sum is the highest.

Solution

If you haven’t read the article detailing how I’m setting up my projects for AoC, I recommend you do that before continuing to read.

Inside my src/part_one/mod.rs, I’m importing the following files:

use crate::args;

use std::fs::File;
use std::io::{BufRead, BufReader};

This simply lets us read from the input.txt file that contains our input from the AoC website. Then we define an Elf struct to help us later.

#[derive(Debug, Clone, Copy)]
pub struct Elf {
    pub total_calories: u32,
}

Now that the boring stuff is out of the way, let’s move onto the run function:

pub fn run(a: args::Arguments) {

The signature of this function is really straight-forward. We take in an args::Arguments struct that has all the info we need to run.

let mut elves: Vec<Elf> = Vec::new();
let mut e = Elf { total_calories: 0 };
let mut max_elf = 0;

First we create a vector of elves and create an index for the max elf. If I were to do this again, I would probably just store the max_sum_of_calories here.

let file = match File::open(a.get_input()) {
    Err(e) => panic!("Could not open file: {}", e),
    Ok(file) => file,
};

let reader = BufReader::new(file);

Here, I very jankily read from the file and create something to iterate on. In later days I clean this part up a fair bit.

for (_index, line) in reader.lines().enumerate() {
    let line = line.unwrap(); // Ignore errors
    if line.is_empty() {
        elves.push(e);

        if e.total_calories > elves.get(max_elf).unwrap().total_calories {
            max_elf = elves.len() - 1;
        }

        e = Elf { total_calories: 0 }
    } else {
        let c = line.parse::<u32>().unwrap();
        e.total_calories += c;
    }
}

This is the meat and potatoes of the solution. If the line isn’t blank, that means it’s a calorie and we should add it to the current elf. If the line is blank, that means we need to push the elf into the vector, and create a new elf to play with. We also update the index for max_elf if we have a new max calories.

println!("D01P1 {}", elves.get(max_elf).unwrap().total_calories);

Finally, we get the total calories from the max elf and print it to the console.

part_one/mod.rs
use crate::args;

use std::fs::File;
use std::io::{BufRead, BufReader};


pub struct Elf {
    pub total_calories: u32,
}

pub fn run(a: args::Arguments) {
    let mut elves: Vec<Elf> = Vec::new();
    let mut e = Elf { total_calories: 0 };
    let mut max_elf = 0;

    let file = match File::open(a.get_input()) {
        Err(e) => panic!("Could not open file: {}", e),
        Ok(file) => file,
    };

    let reader = BufReader::new(file);

    // @REF [Read a file line by line](https://riptutorial.com/rust/example/4275/read-a-file-line-by-line)
    for (_index, line) in reader.lines().enumerate() {
        let line = line.unwrap(); // Ignore errors
        if line.is_empty() {
            elves.push(e);

            if e.total_calories > elves.get(max_elf).unwrap().total_calories {
                max_elf = elves.len() - 1;
            }

            e = Elf { total_calories: 0 }
        } else {
            let c = line.parse::<u32>().unwrap();
            e.total_calories += c;
        }
    }

    println!("D01P1 {}", elves.get(max_elf).unwrap().total_calories);
}

Part Two

Problem

Now we need to keep track of the top three elves by calorie.

Solution

This solution is largely the same as part one. The change is entirely in the run function.

let mut elves: Vec<Elf> = Vec::new();
let mut e = Elf { total_calories: 0 };
let mut elf_one = 0;
let mut elf_two = 0;
let mut elf_three = 0;

We still have the same elves vector, but we keep track of the indices of the top three elves.

if e.total_calories > elves.get(elf_one).unwrap().total_calories {
    elf_three = elf_two;
    elf_two = elf_one;
    elf_one = elves.len() - 1;
} else if e.total_calories > elves.get(elf_two).unwrap().total_calories {
    elf_three = elf_two;
    elf_two = elves.len() - 1;
} else if e.total_calories > elves.get(elf_three).unwrap().total_calories {
    elf_three = elves.len() - 1;
}

We also change how we update these indices.

let total_calories = elves.get(elf_one).unwrap().total_calories
    + elves.get(elf_two).unwrap().total_calories
    + elves.get(elf_three).unwrap().total_calories;

println!("D01P2 {}", total_calories);

Finally we print out the sum of the max three calories.

part_two/mod.rs
use crate::args;

use std::fs::File;
use std::io::{BufRead, BufReader};


pub struct Elf {
    pub total_calories: u32,
}

pub fn run(a: args::Arguments) {
    let mut elves: Vec<Elf> = Vec::new();
    let mut e = Elf { total_calories: 0 };
    let mut elf_one = 0;
    let mut elf_two = 0;
    let mut elf_three = 0;

    // @REF [Read a file line by line](https://riptutorial.com/rust/example/4275/read-a-file-line-by-line)
    let file = match File::open(a.get_input()) {
        Err(e) => panic!("Could not open file: {}", e),
        Ok(file) => file,
    };

    let reader = BufReader::new(file);

    for (_index, line) in reader.lines().enumerate() {
        let line = line.unwrap(); // Ignore errors
        if line.is_empty() {
            elves.push(e);

            if e.total_calories > elves.get(elf_one).unwrap().total_calories {
                elf_three = elf_two;
                elf_two = elf_one;
                elf_one = elves.len() - 1;
            } else if e.total_calories > elves.get(elf_two).unwrap().total_calories {
                elf_three = elf_two;
                elf_two = elves.len() - 1;
            } else if e.total_calories > elves.get(elf_three).unwrap().total_calories {
                elf_three = elves.len() - 1;
            }

            e = Elf { total_calories: 0 }
        } else {
            let c = line.parse::<u32>().unwrap();
            e.total_calories += c;
        }
    }

    let total_calories = elves.get(elf_one).unwrap().total_calories
        + elves.get(elf_two).unwrap().total_calories
        + elves.get(elf_three).unwrap().total_calories;

    println!("D01P2 {}", total_calories);
}