Advent of Code 2019 Day 1 (Part 2) PHP Hints

— Day 1: The Tyranny of the Rocket Equation (Part 2) —

So we got through Day 1 Part 1 and a lot of the ground work with setting up the test suite to handle inputs and outputs – it should all be plain sailing from here! Well maybe…

The first impressions of the Part 2 puzzle description

However, that fuel also requires fuel, and that fuel requires fuel, and so on.

(and from what I know about the real rocket equation) is that this part could be solved with some kind of recursion or while loop.

So again the first thing I want to do is to set up my tests using the inputs and outputs provided. I created /tests/Puzzle1Part2Test.php replacing FuelCounterUpper with FuelCounterUpper2:

/tests/Puzzle1Part2Test.php

<?php

use PHPUnit\Framework\TestCase;
use PuzzleSolvers\Puzzle1\FuelCounterUpper2;

final class Puzzle1Part2Test extends TestCase
{
    public function testInputs(): void
    {
        $outputs = [2, 966, 50346];
        foreach ($outputs as $inputFileNumber => $output) {
            $puzzleSolver = new FuelCounterUpper2('puzzle1/part2/' . $inputFileNumber . '.txt');
            $puzzleSolver->run();
            $this->assertSame($output, $puzzleSolver->getOutput());
        }
    }
}

And then created new input files in /inputs/puzzle1/part2/

/inputs/puzzle1/part2/0.txt

14

/inputs/puzzle1/part2/1.txt

1969

/inputs/puzzle1/part2/2.txt

100756

FuelCounterUpper2 is just a direct copy of FuelCounterUpper to begin with

/src/puzzle1/FuelCounterUpper2.php

<?php

namespace PuzzleSolvers\Puzzle1;

use PuzzleSolvers\PuzzleSolver;

class FuelCounterUpper2 extends PuzzleSolver
{
    public function run()
    {
        $this->output = 0;

        foreach ($this->inputs as $mass) {
            $this->output += $this->calculateFuelForMass($mass);
        }
    }

    public function calculateFuelForMass($mass)
    {
        return (int) floor($mass / 3) - 2;
    }
}

Next running make tests shows that we’re still passing for the first input but not the others:

There was 1 failure:

1) Puzzle1Part2Test::testInputs
Failed asserting that 654 is identical to 966.

With that setup out of the way it was time to dig into the new requirements a bit more and work out what was missing.

for each module mass, calculate its fuel and add it to the total. Then, treat the fuel amount you just calculated as the input mass and repeat the process

So how do we achieve this?

Basically we want to calculate fuelForModules by running $mass = $this-&gt;calculateFuelForMass($mass); inside a while loop until the mass becomes less than 0. Then add that to the total output.

public function run()
{
    $this->output = 0;

    foreach ($this->inputs as $mass) {
        $fuelForModule = 0;

        while ($mass > 0) {
            $mass = $this->calculateFuelForMass($mass);
            $fuelForModule += $mass;
        }
        $this->output += $fuelForModule;
    }
}

But make tests showed that this was failing giving an output of 0 instead of 2 for the input of 14. I realised that the second time through the while loop was returning a mass of -2 and was not being ignored.

Any mass that would require negative fuel should instead be treated as if it requires zero fuel;

The next change was to only add mass when greater than zero:

if ($mass > 0) {
    $fuelForModule += $mass;
}

Now make tests all passed! As in part 1 – I combined the inputs and outputs to create a new multi-line test case

/inputs/puzzle1/part2/3.txt

14
1969
100756

And updated the outputs array in /tests/Puzzle1Part2.php

$outputs = [2, 966, 50346, (2 + 966 + 50346)];

make tests all passed. So next I updated my solve.php script to provide answers to both parts:

/src/puzzle1/solve.php

<?php

require_once __DIR__ . '/../../vendor/autoload.php';

use PuzzleSolvers\Puzzle1\FuelCounterUpper;
use PuzzleSolvers\Puzzle1\FuelCounterUpper2;

$fuelCounterUpper = new FuelCounterUpper('puzzle1/input.txt');
$fuelCounterUpper->run();
echo "Part 1 answer: " . $fuelCounterUpper->getOutput() . "\n";

$fuelCounterUpper2 = new FuelCounterUpper2('puzzle1/input.txt');
$fuelCounterUpper2->run();
echo "Part 2 answer: " . $fuelCounterUpper2->getOutput() . "\n";

Let’s get that gold star!

$ php src/puzzle1/solve.php
Part 1 answer: 3464458
Part 2 answer: 5193796

The final code for this part can be found on GitHub here. Remember my answer will not be the same as yours for your real input. Make sure to replace your inputs/puzzle1/input.txt with your own file. Did it work? Let me know!

Next up: Day 2 Part 1

Leave a comment

Your email address will not be published. Required fields are marked *