## DEV Community 👩‍💻👨‍💻 Jon Bristow

Posted on • Updated on

# Advent of Code 2019 Solution Megathread - Day 1: The Tyranny of the Rocket Equation

Well, we're off to a running start! Since the leaderboard is safely locked, we can go ahead and post our solutions now!

### Day 1 - The Problem

Looks like Santa got himself in a bit of trouble this year! Seems like we're not dealing with time shenanigans, printer trouble, high-precision clock fueling or weather machine woes. This year we need to get Santa and his sleigh back from the edge of space.

But first... we need to get to him. Getting to him requires fuel. Let's calculate how much we'll need to make the trip.

Part 1 of this problem was a nice straightforward warmup. Part 2 was only a little bit trickier than the first, but I overthought it and gave myself the wrong answer anyway.

### Ongoing Meta

If you were part of Ryan Palo's leaderboard last year, you're still a member of that!

I'll edit in any leaderboards that people want to post, along with any description for the kinds of people you want to have on it. (My leaderboard is being used as my office's leaderboard.) And if I get something wrong, please call me out or message me and I’ll fix it ASAP.

There's no limit to the number of leaderboards you can join, so there's no problem belonging to a "Beginner" and a language specific one if you want.

#### Neat Statistics

I'm planning on adding some statistics, but other than "what languages did we see yesterday" does anyone have any ideas? Linda Thompson

I would love to be part of some DEV leaderboards! I'm not showing myself as part of any right now, and am more than willing to use my own private one as a DEV-centric one if we need it. :) Do we have a way to share those so we can start joining?

I'll be doing my solutions in JavaScript - they're usually fairly verbose, since it helps me think better that way. lol :) So likely pretty beginner-friendly!

Here's day 1's solutions:

``````const fs = require('fs');
const input = data.split('\r\n').map(Number);
const testInput = [
14,
1969,
100756
];

// mass / 3, round down, -2
function formula(mass) {
return Math.floor(mass / 3) - 2;
}

// Part 1
const fuelOfMass = input.map((curr) => {
return formula(curr);
});

const totalFuel = fuelOfMass.reduce((acc, curr) => {
return acc + curr;
}, 0);

console.log(`Part 1: \${totalFuel}`);

// Part 2

const totalFuelOfMass = input.map((curr) => {
let value = curr;
let accumulator = [];

do {
value = formula(value);
if (value > 0) {
accumulator.push(value);
}
} while (value > 0);

return accumulator.reduce((acc, curr) => {
return acc + curr;
}, 0);
});

const newTotalFuel = totalFuelOfMass.reduce((acc, curr) => {
return acc + curr;
}, 0);

console.log(`Part 2: \${newTotalFuel}`);
`````` Jacque Schrag

Ooh this is a great use of `do...while`. I went with the less elegant nested `if` for mine 😅

## Part 1 (JavaScript)

``````const fs = require("fs");
const path = require("path");
const text = fs.readFileSync(path.join(__dirname) + "/input.txt", "utf8");
let output = text
.split("\n")
.map(d => calcFuelPerModule(d))
.reduce((acc, curr) => acc + curr, 0);
console.log(output);

function calcFuelPerModule(mass) {
return Math.floor(+mass / 3) - 2;
}
``````

## Part 2 (JavaScript)

``````const fs = require("fs");
const path = require("path");
const text = fs.readFileSync(path.join(__dirname) + "/input.txt", "utf8");
let output = text
.split("\n")
.map(d => calcFuel(d))
.reduce((acc, curr) => acc + curr, 0);
console.log(output);

function calcFuel(mass) {
let fuel = calcFuelPerModule(mass);
if (fuel > 0) {
let fuelFuel = calcFuel(fuel);
if (fuelFuel > 0) {
fuel += calcFuel(fuel);
}
}
return fuel;
}

function calcFuelPerModule(mass) {
return Math.floor(+mass / 3) - 2;
}
`````` Linda Thompson

Still works well! As long as it gets you the answer, it's good! :)

I saw someone use a ternary operator, and was super impressed. Might refactor mine later today to test that. :) Didn't even think of it! Linda Thompson

Also, I couldn't resist the idea of the poem challenge they're doing on the subreddit, so I wrote an acrostic. :) Sharing here as well!

Discover the cosmos
Venture into the unknown
Earn fifty stars to save Christmas!
No one goes alone, however
There's friendly folks to help

Overly dramatic situations await
Find Santa and bring him home!

Come code with us!
Outer space is calling
Don't be afraid
Elves will guide the way! Brandon Schreck • Edited on

Very nice, I need to step my JS game up!

``````const data = [148216, 142030, 129401, 74642, 108051, 54128, 145495, 67818, 120225, 67113,
107672, 101032, 147714, 55788, 87732, 73681, 114646, 76586, 116436, 139788, 125150, 136675,
90527, 74674, 105505, 146059, 52735, 101389, 108121, 62897, 132337, 51963, 129188, 122308,
84677, 66433, 118374, 66822, 94714, 101162, 54030, 136580, 55677, 114051, 133898, 95026,
112964, 68662, 85139, 53559, 84703, 92053, 132197, 60130, 63184, 86182, 113038, 52659,
140463, 123234, 97887, 70216, 131832, 108162, 116759, 111828, 132815, 113476, 127734,
134545, 99643, 141911, 74705, 65720, 95640, 51581, 66787, 147590, 72937, 148774,
119881, 139875, 131976, 68238, 100342, 134691, 112320, 86107, 100045, 120458,
54459, 52047, 108226, 102138, 141233, 54452, 67859, 105132, 81903, 104282];

function calculateFuel(mass) {
return Math.floor(mass / 3) - 2;
}

function getTotalFuel(mass) {
let fuel = calculateFuel(mass);
return fuel > 0 ? fuel += getTotalFuel(fuel) : 0;
}

function outputTestResults(index, testCase, result) {
console.log(`Test \${ index + 1 }\n` +
`Input: \${ testCase.input }\n` +
`Expected Result: \${ testCase.output }\n` +
`Result: \${ result }\n` +
`Passes Test: \${ testCase.output === result }\n\n`);
}

// Part One
console.log(`Begin Part One`);
let partOneResult = 0;
const partOneTestCases = [{
input: 12,
output: 2
},
{
input: 14,
output: 2
},
{
input: 1969,
output: 654
},
{
input: 100756,
output: 33583
},
];

// part one test cases
partOneTestCases.forEach(function(testCase, index) {
outputTestResults(index, testCase, calculateFuel(testCase.input));
});

// part one do work
data.forEach(function(mass) {
partOneResult += calculateFuel(mass);
});

// Part Two
console.log(`Begin Part Two`);
let partTwoResult = 0;
const partTwoTestCases = [{
input: 14,
output: 2
},
{
input: 1969,
output: 966
},
{
input: 100756,
output: 50346
}
];

// part two test cases
partTwoTestCases.forEach(function(testCase, index) {
outputTestResults(index, testCase, getTotalFuel(testCase.input));
});

// do work
data.forEach(function(mass) {
partTwoResult += getTotalFuel(mass);
});
`````` Jon Bristow

Post it here and I'll add it to the post and on further days posts! Go to you private leaderboard page and copy the code into a reply. Linda Thompson

Alright, here's the code - 120635-5c140b9a.

We can make it for basically anyone on DEV, or we can focus it towards more beginner-friendly if we'd like - whatever works best for everyone! Christopher Kruse

Awesome! Thanks for creating a leaderboard for DEV. Ben Sinclair

I'm in. Jon Bristow • Edited on

My kotlin solution.

``````import java.nio.file.Files
import java.nio.file.Paths
import kotlin.math.max

private const val FILENAME = "src/main/resources/day01.txt"

fun fuelNeeded(mass: Int) = max((mass / 3) - 2, 0)

fun totalFuelNeeded(mass: Int): Int {
var fuel = fuelNeeded(mass)
var totalFuel = fuel
while (fuel != 0) {
fuel = fuelNeeded(fuel)
totalFuel += fuel
}
}

.sumBy { fuelNeeded(it.toInt()) }
.toString()

.sumBy { totalFuelNeeded(it.toInt()) }
.toString()

fun main() {
println("Part 1: \${part1()}")
println("Part 2: \${part2()}")
}
``````

I'm going to clean this up to avoid imperative style and post it as a reply to this comment. Jon Bristow

This part 2 solution is much more elegant, and leverages monads.

``````tailrec fun totalFuelNeeded(mass: Int, fuel: Option<Int> = Option.empty(), totalFuel: Int = 0): Int =
when (val nextFuel = fuel.fold({ fuelNeeded(mass) }, ::fuelNeeded)) {
0 -> totalFuel
else -> totalFuelNeeded(mass, nextFuel.just(), totalFuel + nextFuel)
}
`````` Christopher Kruse

I didn't even think about using a `max` function - that would have been so much cleaner than making two functions! Jon Bristow

I love cleaning these up into more elegant forms almost as much as I love just getting the solution banged out! Christopher Kruse • Edited on

Solution in Clojure:

``````(ns ballpointcarrot.aoc
(:require [clojure.string :as st]))

(defn fuel-cost
[value]
(- (Math/floor (/ value 3)) 2))

[value]
(let [fuel (fuel-cost value)]
(if (pos? fuel)
fuel
0)))

(defn p2019-01
"Calculate Fuel requirements"
[input]
(apply +
(map #(fuel-cost (Integer/parseInt %)) (st/split-lines input))))

(defn recursive-fuel-cost
[value]
(loop [remains value
total 0]
(if (= remains 0)
total
(recur fuel (+ total fuel))))))

(defn p2019-01-part2
"Calculate fuel requirements, including weight of fuel"
[input]
(apply +
(map #(recursive-fuel-cost (Integer/parseInt %)) (st/split-lines input))))

`````` Neil Gall

Yay, Advent of Code is back. I'm not going to stick to one programming language this year, in fact I'm going to try to use lots, even some I've not used before. I'm not quite hardcore enough to do the different-language-every-day challenge however. Not this year anyway.

``````import Test.Hspec

moduleFuel :: Int -> Int
moduleFuel mass = (mass `div` 3) - 2

fuelFuel :: Int -> Int
fuelFuel fuel = fuel + fuel' (moduleFuel fuel)
where
fuel' f = if f <= 0 then 0 else fuelFuel f

part1 :: [Int] -> Int
part1 = sum . map moduleFuel

part2 :: [Int] -> Int
part2 = sum . map (fuelFuel . moduleFuel)

testModuleFuel = do
moduleFuel 12 `shouldBe` 2
moduleFuel 14 `shouldBe` 2
moduleFuel 1969 `shouldBe` 654
moduleFuel 100756 `shouldBe` 33583

testFuelFuel = do
fuelFuel 2 `shouldBe` 2
fuelFuel 654 `shouldBe` 966
fuelFuel 33583 `shouldBe` 50346

test = do
testModuleFuel
testFuelFuel

main = do
test
putStrLn \$ "Part 1 : " ++ (show \$ part1 input)
putStrLn \$ "Part 2 : " ++ (show \$ part2 input)
``````

Once it was solved I did it again in Python just for fun:

``````from typing import Sequence

with open(file, "rt") as f:
return list(int(line) for line in f.readlines())

def moduleFuel(mass: int) -> int:
return (mass // 3) - 2

def fuelFuel(mass: int) -> int:
f = moduleFuel(mass)
return mass + (0 if f <= 0 else fuelFuel(f))

def testModuleFuel():
assert(moduleFuel(12) == 2)
assert(moduleFuel(14) == 2)
assert(moduleFuel(1969) == 654)
assert(moduleFuel(100756) == 33583)

def testFuelFuel():
assert(fuelFuel(2) == 2)
assert(fuelFuel(654) == 966)
assert(fuelFuel(33583) == 50346)

def part1(modules: Sequence[int]) -> int:
return sum(moduleFuel(f) for f in modules)

def part2(modules: Sequence[int]) -> int:
return sum(fuelFuel(moduleFuel(f)) for f in modules)

if __name__ == "__main__":
testModuleFuel()
testFuelFuel()
print(f"Part 1 : {part1(input)}")
print(f"Part 2 : {part2(input)}")
``````

And in the spirit of what I wrote at the top, I did it once more in Julia, my first ever code in that language. First impressions very positive and interestingly it came out shortest. I love the built-in unit testing.

``````using Test

moduleFuel(mass::Int) = div(mass, 3) - 2

function fuelFuel(mass::Int)
f = moduleFuel(mass)
mass + if f <= 0 0 else fuelFuel(f) end
end

@testset "ModuleFuel" begin
@test moduleFuel(12) == 2
@test moduleFuel(14) == 2
@test moduleFuel(1969) == 654
@test moduleFuel(100756) == 33583
end

@testset "FuelFuel" begin
@test fuelFuel(2) == 2
@test fuelFuel(654) == 966
@test fuelFuel(33583) == 50346
end

part1(modules) = sum(moduleFuel(m) for m in modules)

part2(modules) = sum(fuelFuel(moduleFuel(m)) for m in modules)

println("Part 1 : \$(part1(input))")
println("Part 2 : \$(part2(input))")
`````` Linda Thompson

Hey folks - for anyone who's joined the leader board so far - I have a question!

So there are two main ways to sort our leader board, and I'm wondering which option would be best for us.

Option 1 - It counts how many people belong to the leader board (n), then the first user to get each star gets N points, the second gets N-1, and the last gets 1.

Option 2 - It counts how many stars you have, and then any ties are broken by the time you got the star. So if everyone gets all of the stars, the ones who get them the fastest are higher up.

I think either way is likely fine, but feel like maybe the star sort option might be best - it seems like it would encourage completion of the challenges more so than simply getting them done fastest, but still includes some speed needed to be higher up. Would love to hear some other thoughts on this, and whichever option seems most popular is what I'll sort it by! Avalander

I like option 2 a bit better. I'd rather see the people that manage to solve the more complicated problems at the top than those who solved the first few problems the fastest. My solution using Rust.

``````
fn part_a(input: Vec<u32>) {
let output: u32 = input.iter().map(|val| (val - (val % 3)) / 3 - 2).sum();
println!("{:?}", output);
}

fn part_b(input: Vec<u32>) {
let output: u32 = input.iter().map(|val| rec_fuel_calc(*val)).sum();
println!("{:?}", output);
}

fn rec_fuel_calc(mass: u32) -> u32 {
let answer = ((mass - (mass % 3)) / 3) - 2;
} else {
}
}
`````` Ryan Palo

This was a good ramp into the month! Here's my Rust solution. :)

``````/// Day 1: The Tyranny of the Rocket Equation
///
/// Calculate the amount of fuel required to launch your spaceship!

use std::fs::File;
use std::io::prelude::*;

/// Calculate the fuel required to lift one module, based on its mass
fn fuel_required(mass: &usize) -> usize {
(mass / 3) - 2
}

/// Calculates the fuel required to lift one module, but factors in the
/// weight of the fuel as well
fn recursive_fuel_required(mass: &usize) -> usize {
if *mass <= 6 {
0
} else {
let next_mass = (mass / 3) - 2;
next_mass + recursive_fuel_required(&next_mass)
}
}

/// Calculate the total fuel requirements for the launch
fn fuel_requirements(module_masses: Vec<usize>) -> usize {
module_masses.iter().map(recursive_fuel_required).sum()
}

/// Parses the input file, which is a bunch of numbers, one per line
fn parse_input() -> Vec<usize> {
buf.lines()
.map(|result| result.unwrap())
.map(|line| line.parse::<usize>().unwrap())
.collect()
}

/// Main day 1 code
pub fn run() {
let data = parse_input();
let total_requirements = fuel_requirements(data);
println!("Total fuel required: {}", total_requirements);
}
`````` Joshua Blewitt

This is my solution to Part 1 in Ruby - working on Part 2!

``````#advent of code day 1
#lets open the input file
target = File.open("input.txt")
#part 1
def calculation (file)
total = 0
file.each{|number|
number = number.to_i / 3 - 2
total += number
}
puts "Our total is - #{total}"
end

calculation(target)
target.close
`````` Sarah

I joined the leaderboard, but since I'm in a EU timezone and only have time to work on them in the evenings I'm expecting my scores to be quite low 😅

Here's my solution for day 1 with Python (explained my thinking behind it here):

Part 1:

``````input = np.array([input])
output = np.sum(np.floor(input / 3) - 2)
``````

Part 2:

``````for module in input_array:
new_fuel = mod
while True:
new_fuel = np.floor(new_fuel / 3) - 2
if new_fuel > 0:
total_fuel += new_fuel
else:
break
`````` Rizwan

Bit late to the party!

Here is my solution in swift. Incase anyone would like followup code can be found here in Github

``````func fuel(forMass mass: Int) -> Int {
return Int((Double(mass) / 3).rounded(.down) - 2)
}

func partOne() {
var total = 0
input.components(separatedBy: .newlines).map{ input in
total = total + fuel(forMass: Int(input) ?? 0)
}
print(total)
}

func fuel(forMass mass: Int, includesFuelMass: Bool) -> Int {
if !includesFuelMass {
return fuel(forMass: mass)
}

var currentFuel = mass
var total = 0
while true {
let fuels = fuel(forMass: currentFuel)
if fuels < 0 {
break
}
currentFuel = fuels
total = total + currentFuel
}
}

func partTwo() {
var total = 0
input.components(separatedBy: .newlines).map{ input in
total = total + fuel(forMass: Int(input) ?? 0, includesFuelMass: true)
}
print(total)
}

partOne()
partTwo()
`````` Elixir way

Day 01

``````defmodule Day01 do
def mass_calc([]), do: 0
def fuel(mass), do: floor(mass / 3) - 2
end

Day01.mass_calc([146561, 98430, 131957, 81605, 70644, 55060, 93217, 107158, 110769, 94650, 141070, 72381, 100736, 105705, 99003, 94057, 110662, 74429, 55509, 63492, 102007, 72627, 95183, 112072, 122313, 116884, 125451, 106093, 140678, 121751, 149018, 58459, 138306, 149688, 82927, 72676, 95010, 88439, 51807, 103175, 107633, 126439, 128879, 112054, 52873, 114493, 77365, 76768, 60838, 89692, 66217, 96060, 100338, 139063, 126869, 106490, 128967, 116312, 56822, 52422, 124579, 117120, 106245, 105255, 66975, 115340, 145764,
149427, 64228, 64237, 67887, 103345, 134901, 50226, 126991, 122314, 140818, 129687, 149792, 101148, 73411, 87078, 121272, 108804, 96063, 81155, 62058, 112684, 134263, 128454, 99455, 91689, 141448, 143892, 103257, 64352, 90769, 78307, 111855, 130153])
`````` dimitri • Edited on

I'm also participating this year. I want to solve everything in JS, as I'm new to web development (mostly frontend with React) on my job, too.

## Part1

``````var fs = require("fs");
var textByLine = text.split("\n");

var sum = 0;

for(i=0; i < textByLine.length; i++){
textByLine[i] = parseInt(textByLine[i]);
textByLine[i] = Math.floor(textByLine[i]/3)-2;
sum += textByLine[i];
}
console.log(sum);

``````

## Part2

``````var fs = require("fs");
var textByLine = text.split("\n");

var sum = 0;
var fuels = [];

function calculateFuel(module){
if(module > 0) {
module = Math.floor(module/3)-2;
if (module > 0) {
fuels.push(module)
} else {
return null;
}
calculateFuel(module);
} else {
return null;
}
}

for(i=0; i < textByLine.length; i++){
textByLine[i] = parseInt(textByLine[i]);
textByLine[i] = calculateFuel(textByLine[i]);
}

for(j=0; j < fuels.length; j++){
sum += fuels[j];
}

console.log(sum);

``````

It took my quiet some time, especially for the file IO as there are so many approaches. Yordi Verkroost

Day 1, always good to start nice and easy!

Solution for part two:

``````defmodule Aoc19.Day1b do
@moduledoc false

alias Aoc19.Utils.Common
alias Aoc19.Utils.Day1, as: Day1Utils

def start(input_location) do
input_location
|> Enum.reduce(0, &fuel/2)
|> trunc()
end

def fuel(0, total), do: total

def fuel(mass, total) do
fuel =
mass
|> Day1Utils.fuel()
|> Kernel.max(0)

fuel(fuel, total + fuel)
end
end
``````

And here is part one

## 50 CLI Tools You Can't Live Without The top 50 must-have CLI tools, including some scripts to help you automate the installation and updating of these tools on various systems/distros.