Photography
The backgrounds for these websites are courtesy of these two fantastically talented photographers:
- Sam Egan TRU Marketing & Communications: Main Page
- Alex Binaei Windsor Updates: Projects, About, Blog Pages
Advent of Code 2019 - Day 1
My day job now doesn’t involve a lot of coding, so I’m going to try to stick with Advent of Code ideally through the entire event as a good opportunity to code every day. Also figured it’d be a decent opportunity to do writeups as part of this blog and get some content in here.
For those not familiar with the Advent of Code event, you can find more info on the official website but in short it works like this: the author publishes an Advent-themed problem a day (it two parts, and you cannot access part two until you’ve correctly solved part 1), and people rush to solve it. There’s an overall leaderboard as well as private ones so you can compete against your friends. The overall leaderboard is out of reach for people like me, but it’s fun to compete against your friends and keep at it.
I was originally planning on writing solutions in PHP to practice as I’m very, very rusty on PHP but because I actually started to get into it, I switched back to Python so I could be somewhat useful. Still planning on porting after what I can (based on time constraints) to other languages (primarily PHP and JS).
Note: I’m preparing these writes up a few days after the series started, and backdating them for consistenty. I also am using a cleaned up versions of my original solutions in the interest of clarity (and because it is not that helpful to see the horrible shortcuts I imagined would save me time), however I will call out differences where it may be interesting to do so, and all the history is available on a GitHub repository.
Part 1 was pretty straightforward, it basically asked to find the fuel needed to send to space a number of moduels with a given mass. We are given a simple formula for obtaining the mass: floor(mass/3)-2
with a minimum allowable value of 0.
Saved the input as a basic text file, and simply read each line and turn it into an integer value:
with open('../inputs/01', 'r') as f:
lines = f.readlines()
lines = [int(line.strip()) for line in lines]
Next, I figure we can store the fuel calculation as a basic function and map it over the values:
import math
def calc_fuel(line):
val = math.floor(line/3.0) - 2
return val if val > 0 else 0
fuels = list(map(calc_fuel, lines))
However mapping isn’t the most python construct really, but my mind was very much thinking in Javascript I guess. Here it is with list comprehensions:
fuels = [calc_fuel(line) for line in lines]
Now, again with my mind tuned to Javascript I guess, I figured a reduce would be the easiest way:
from functools import reduce
result_part_1 = reduce(lambda acc, val: acc + val, fuels)
result_part_1
And that works!
In part 2, we’re reminded that fuel has a mass too, and thus any fuel needed for the modules. This is really a recursive idea, where we add the fuel, then we compute the fuel for the additional fuel, and so on. And it ends pretty quickly in the recursion because of the nature of the formula and the value of 0.
So really what we need here is to modify the existing fuel calculation to take into account the recursive mass aspect and re-apply the same map/reduce approach:
def calc_fuel_with_fuel(line):
module_fuel = calc_fuel(line)
total_fuel = module_fuel
residual_fuel = module_fuel
while residual_fuel > 0:
residual_fuel = calc_fuel(residual_fuel)
total_fuel += residual_fuel
return total_fuel
fuels_two = list(map(calc_fuel_with_fuel, lines))
result_part_2 = reduce(lambda acc, val: acc + val, fuels_two)
result_part_2
I had originally solved Day 1 in PHP and the above Python solution is really a mirror of the former (down to the map/reduce approach):
<?php
$input_string = file_get_contents('../inputs/01');
$inputs = explode(PHP_EOL, $input_string);
// Part 1
function calc_fuel($mass)
{
$val = ((int)floor($mass / 3.0)) - 2;
return $val >= 0 ? $val : 0;
}
$fuels = array_map('calc_fuel', $inputs);
$result = array_reduce($fuels, function ($cumulative, $value) {
return $cumulative += $value;
});
echo(sprintf("Result 1: %d\n", $result));
// Part 2
function calc_fuel_with_fuel($mass)
{
$module_fuel = calc_fuel($mass);
$total_fuel = $module_fuel;
$residual_fuel = $module_fuel;
while ($residual_fuel > 0) {
$residual_fuel = calc_fuel($residual_fuel);
$total_fuel += $residual_fuel;
}
return $total_fuel;
}
$fuels_2 = array_map('calc_fuel_with_fuel', $inputs);
$result_2 = array_reduce($fuels_2, function ($cumulative, $value) {
return $cumulative += $value;
});
print sprintf("Result 2: %d\n", $result_2);
print("\n");
I don’t think there’s much worth commenting here as it’s the exact same approach and calculations.
Likewise JavaScript (as a Nodejs script) is obviously similar, though probably the most concise iteration:
let fs = require('fs')
const lines = fs.readFileSync('../inputs/01').toString().split('\n')
function calc_fuel(item) {
const fuel = Math.floor(parseFloat(item) / 3.0) - 2
return fuel > 0 ? fuel : 0
}
const fuels_sum = lines.reduce((acc, i) => acc + calc_fuel(i), 0)
console.log(`Result 1: ${fuels_sum}`)
// Part 2
function calc_fuel_with_fuel(item) {
total_fuel = residual_fuel = calc_fuel(item)
while (residual_fuel > 0) {
residual_fuel = calc_fuel(residual_fuel)
total_fuel += residual_fuel
}
return total_fuel
}
const fuels_sum_2 = lines.reduce((acc, i) => acc + calc_fuel_with_fuel(i), 0)
console.log(`Result 2: ${fuels_sum_2}`)
Credits