Introduction
Since I'm dabbling with Rust, I wanted to see if I could do some of the Advent of Code using it. I'm nowhere near as proficient in Rust as I am in Clojure, so I don't expect to do some of the later challenges, but Day 1 is relatively friendly.
Day 1.1
I did one very simple approach and one that used functions implemented on a custom type. The latter is overkill for this, but it scales well when inputs are used multiple times. Implementing functions on the type reduces boilerplate later.
Anyway, here's the simple:
fn main() {
let day1: Vec<u32> = vec![88093, 102524, ***SHORTEN*** 54128, 111698, 84299];
let total_fuel_reqs: u32 = day1.into_iter()
.map(|x| ((x / 3) as u32) - 2)
.sum();
println!("{:?}", total_fuel_reqs);
}
And here's the over-complicated version:
pub struct Day1Inputs{
day1_input: Vec<u32>
}
impl Day1Inputs {
fn day1_1(self) -> u32 {
let total_fuel_reqs: u32 = self.day1_input
.into_iter()
.map(|x| ((x / 3) as u32) - 2)
.sum();
total_fuel_reqs
}
}
fn main() {
let day1 = Day1Inputs {day1_input: vec![88093, 102524, ***SHORTEN*** 54128, 111698, 84299]};
let fuel_req = day1.day1_1();
(println!("Day 1: {:?}", fuel_req));
}
Day 1.2
I stuck with the implementation approach for this part. Recursion is a little less easy in Rust than Clojure (mainly because Clojure lets you stick a recur
at the end of your loop and does everything else for you). As such, I built a recursion into day1_2
.
One copy event to create a local version of the object mass that can be reduced with each loop as the new fuel mass is returned: fuel_req
One variable to catch the aggregating mass for the individual object and its fuel: total_fuel_mass_for_object
One variable to catch the aggregating mass for all objects: total_fuel_mass
An extra function was needed to hold the fuel calculation this time: day1_2_fuel_calc
.
You'll notice that this function can't be called with self
as it doesn't use self
as an argument. This means it must be accessed via the double-colon approach: Day1Inputs::day1_2_fuel_calc
All previous u32
values were switched to i32
as the recursive fuel calculation can produce negative integers causing the code to panic if it is dealing with u32
.
Then I create a new instance of the type since Vec
can't implement Copy
, preventing me from passing it to the day1_2
code after using it in day1_1
.
pub struct Day1Inputs{
day1_input: Vec<i32>
}
impl Day1Inputs {
fn day1_1(self) -> i32 {
let total_fuel_reqs: i32 = self.day1_input.iter().map(|x| ((x / 3) as i32) - 2).sum();
total_fuel_reqs
}
fn day1_2_fuel_calc(mass: i32) -> i32 {
let new_mass = ((mass / 3) as i32) -2;
new_mass
}
fn day1_2(self) -> i32 {
let mut total_fuel_mass: i32 = 0;
for mass in self.day1_input {
let mut total_fuel_mass_for_object: i32 = 0;
let mut fuel_req = mass;
loop {
fuel_req = Day1Inputs::day1_2_fuel_calc(fuel_req);
if fuel_req <= 0 {
break;
}
total_fuel_mass_for_object = total_fuel_mass_for_object + fuel_req;
}
total_fuel_mass = total_fuel_mass + total_fuel_mass_for_object;
}
total_fuel_mass
}
}
fn main() {
let day1_1 = Day1Inputs {day1_input: vec![88093, 102524, ***SHORTEN*** 54128, 111698, 84299]};
let fuel_req = day1_1.day1_1();
(println!("Day 1.1: {:?}", fuel_req));
let day1_2 = Day1Inputs {day1_input: vec![88093, 102524, ***SHORTEN*** 54128, 111698, 84299]};
let total_fuel_req = day1_2.day1_2();
(println!("Day 1.2: {:?}", total_fuel_req));
}
Update
I noticed that my repeating the creation of inputs was necessary because I wasn't being smart about ownership. I needed to derive the Clone trait for my new type and then clone it:
// Derive the Clone trait for the new type
#[derive(Clone)]
pub struct Day1Inputs{
day1_input: Vec<i32>
}
impl Day1Inputs {
fn day1_1(self) -> i32 {
let total_fuel_reqs: i32 = self.day1_input.iter().map(|x| ((x / 3) as i32) - 2).sum();
total_fuel_reqs
}
fn day1_2_fuel_calc(mass: i32) -> i32 {
let new_mass = ((mass / 3) as i32) -2;
new_mass
}
fn day1_2(self) -> i32 {
let mut total_fuel_mass: i32 = 0;
for mass in self.day1_input {
let mut total_fuel_mass_for_object: i32 = 0;
let mut fuel_req = mass;
loop {
fuel_req = Day1Inputs::day1_2_fuel_calc(fuel_req);
if fuel_req <= 0 {
break;
}
total_fuel_mass_for_object = total_fuel_mass_for_object + fuel_req;
}
total_fuel_mass = total_fuel_mass + total_fuel_mass_for_object;
}
total_fuel_mass
}
}
fn main() {
let day1 = Day1Inputs {day1_input: vec![88093, 102524, ***SHORTEN*** 54128, 111698, 84299]};
// Add a clone() to this line, moving a clone, not the original
let fuel_req = day1.clone().day1_1();
(println!("Day 1.1: {:?}", fuel_req));
// Allowing this line to move the original day1 without errors
let total_fuel_req = day1.day1_2();
(println!("Day 1.2: {:?}", total_fuel_req));
}
Top comments (0)