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
Part One
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);
}