Published
Edited
Jul 28, 2020
4 stars
Insert cell
Insert cell
Insert cell
Insert cell
fuelRequired = m => Math.floor(m / 3) - 2
Insert cell
masses = (await FileAttachment("day1input.txt").text())
.split('\n')
.filter(x => x)
.map(x => parseInt(x))
Insert cell
masses.map(fuelRequired).reduce((acc, x) => acc + x, 0)
Insert cell
Insert cell
Insert cell
leb = require("https://bundle.run/@webassemblyjs/leb128@1.9.0/lib/index.js")
Insert cell
Insert cell
part1Code = mass => [
0x00, // there are no local variables (this is where we'd declare them if there were)
0x41, // constant integer
...leb.encodeI32(mass),
0x41, // constant integer
...leb.encodeI32(3),
0x6D, // division
0x41, // constant integer
...leb.encodeI32(2),
0x6B, // subtraction
0x0B // END opcode
]
Insert cell
Insert cell
buildModule = code => {
return [
...[0x00, 0x61, 0x73, 0x6d], // magic number
...[0x01, 0x00, 0x00, 0x00], // version

0x01, // Type section
0x05, // this section has 5 more bytes
0x01, // There is 1 type
0x60, // it's a function
0x00, // it takes zero arguments
0x01, // it has one return value (I think that's what this means?)
0x7f, // which is an int

0x03, // Func section
0x02, // this section has 2 more bytes
0x01, // there's one function
0x00, // function at index 0 uses type signature at index 0

0x07, // Export section
0x05, // this section has 5 more bytes
0x01, // there's one export
0x01, // the name of the function has one byte
'x'.codePointAt(0), // let's call our exported function "x"
0x00, // it's a function
0x00, // it's the function at index 0

0x0a, // Code section
code.length + 2, // there are code.length + 2 more bytes in this section
0x01, // there's one function in here
code.length, // this function is code.length bytes long
...code
];
}
Insert cell
Insert cell
async function runModule(mass) {
const linear = buildModule(mass);
const linearBuffer = new Uint8Array(linear);
const module = await WebAssembly.compile(linearBuffer);
const instance = await WebAssembly.instantiate(module);
return await instance.exports.x();
}
Insert cell
runModule(part1Code(masses[0]))
Insert cell
Insert cell
(await Promise.all(masses.map(mass => runModule(part1Code(mass))))).reduce(
(acc, x) => acc + x,
0
)
Insert cell
Insert cell
Insert cell
Insert cell
part2Code = mass =>
// prettier-ignore
[
0x01, // What does this do???
0x02, // there are two local variables
0x7f, // and they're all integers
// 0 1
// acc, fuel

0x41, ...leb.encodeI32(mass), // constant integer mass

0x21, 0x01, // store mass in local variable fuel
0x02, 0x40, // start a block
0x03, 0x40, // start a loop block
0x20, 0x01, // get local variable fuel
0x41, ...leb.encodeI32(3), // constant integer 3
0x6D, // division
0x41, ...leb.encodeI32(2), // constant integer 2
0x6B, // subtraction
0x21, 0x01, // store result in local variable fuel

0x20, 0x01, // get local variable fuel
0x41, ...leb.encodeI32(0), // constant integer 0
0x4c, // less than or equal for 2 signed integers
0x0D, 0x01, // break out of loop if true
0x20, 0x00, // get local variable acc
0x20, 0x01, // get local variable fuel
0x6A, // addition
0x21, 0x00, // store result in local variable acc
0x0C, 0x00, // break to start of loop
0x0B,
0x0B,
0x20, 0x00, // get local variable acc
0x0B // end of function
]
Insert cell
runModule(part2Code(masses[0]))
Insert cell
Insert cell
(await Promise.all(masses.map(mass => runModule(part2Code(mass))))).reduce(
(acc, x) => acc + x,
0
)
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more