Preamble

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.

Day 1

Part 1

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!

Part 2

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

PHP

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.

JavaScript

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}`)

Original files


Considering I was running on very little sleep at the time I presented the workshop as I had just returned back from a conference in Germany a few days earlier (and had little time to recover due to schoolwork), I was fairly happy with how my workshop went. I got stuck on a few silly typos and was rescued by the audience, I’m definitively glad I had a step-by-step handout ready for the audience, I definitively tried to refer back to it when possible and it kept me on track I think.

subscribe via RSS