Published
Edited
Oct 12, 2020
Importers
11 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
intCode = (await FileAttachment("day2input.txt").text())
.trim()
.split(',')
.map(x => parseInt(x))
Insert cell
Insert cell
codeWithModuleBoilerplate = code => {
return [
...[0x00, 0x61, 0x73, 0x6d], // magic number
...[0x01, 0x00, 0x00, 0x00], // version

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

0x02, // Import section
0x08, // this section has 8 more bytes
0x01, // there is one thing we import
0x01, // the name of the import namespace has one byte
'e'.codePointAt(0), // let's call our import namespace function "e" ("env" is the usual convention)
0x01, // the name of the memory has one byte
'm'.codePointAt(0), // let's call our import namespace function "m" ("memory" is the usual convention)
0x02, // import/export type "mem"
0x00, // somehow describes the size of the memory section?
0x01, // somehow describes the size of the memory section?

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
part1Code = {
// prettier-ignore
return [
0x01, // What does this do???
0x04, // there are four local variables (in addition to the passed in param)
0x7f, // and they're all integers
// 1 2 3 4
// opcode, operand1, operand2, dest
0x20, 0x00, // load passed-in parameter "location"
0x41, 0x04, // constant integer 4
0x6C, // multiply to get memory address
0x28, 0x02, 0x00, // load the integer at this location
0x21, 0x01, // store result in local variable opcode
0x20, 0x00, // load passed-in parameter "location"
0x41, 0x04, // constant integer 4
0x6C, // multiply to get memory address
0x28, 0x02, 0x04, // load the integer at this location + 4 bytes
0x41, 0x04, // constant integer 4
0x6C, // multiply to get memory address
0x28, 0x02, 0x00, // load the integer at THAT location
0x21, 0x02, // store result in local variable operand1
0x20, 0x00, // load passed-in parameter "location"
0x41, 0x04, // constant integer 4
0x6C, // multiply to get memory address
0x28, 0x02, 0x08, // load the integer at this location + 8 bytes
0x41, 0x04, // constant integer 4
0x6C, // multiply to get memory address
0x28, 0x02, 0x00, // load the integer at THAT location
0x21, 0x03, // store result in local variable operand2
0x20, 0x00, // load passed-in parameter "location"
0x41, 0x04, // constant integer 4
0x6C, // multiply to get memory address
0x28, 0x02, 0x0c, // load the integer at this location + 12 bytes
0x21, 0x04, // store result in local variable dest
0x02, 0x40, // start a block - this one for mult
0x02, 0x40, // start a block - this one for end
0x41, 0x01, // constant integer 1
0x20, 0x01, // get local variable operator
0x46, // are these two integers equal?
0x0D, 0x00, // break out of block if so (add)
0x41, 0x02, // constant integer 2
0x20, 0x01, // get local variable operator
0x46, // are these two integers equal?
0x0D, 0x01, // break out two levels if so (mult)
0x41, 0x7f, // constant integer -1
0x0f, // return -1 meaning intcode program is over
0x0B, // END opcode
0x20, 0x04, // get local variable dest
0x41, 0x04, // constant integer 4
0x6C, // multiply to get index into memory
0x20, 0x02, // get local variable operand1
0x20, 0x03, // get local variable operand2
0x6A, // add operands
0x36, 0x02, 0x00, // store at value at dest
0x20, 0x00, // load passed-in parameter "location"
0x41, 0x04, // constant integer 4
0x6A, // add to get new location
0x0f, // return 1 meaning intcode program is still running
0x0B, // END opcode
0x20, 0x04, // get local variable dest
0x41, 0x04, // constant integer 4
0x6C, // multiply to get index into memory
0x20, 0x02, // get local variable operand1
0x20, 0x03, // get local variable operand2
0x6C, // multiply operands
0x36, 0x02, 0x00, // store at value at dest
0x20, 0x00, // load passed-in parameter "location"
0x41, 0x04, // constant integer 4
0x6A, // add to get new location
0x0B // END opcode
]
}
Insert cell
codeWithModuleBoilerplate(part1Code)
Insert cell
Insert cell
Insert cell
async function buildModule(intCode) {
const pageSize = 65536;
const bytesPerInt = 4;
const memory = new WebAssembly.Memory({
initial: Math.ceil((intCode.length * bytesPerInt) / pageSize)
});
const integers = new Int32Array(memory.buffer);
for (let i = 0; i < intCode.length; i++) {
integers[i] = intCode[i];
}

const importObj = {
e: {
m: memory
}
};

const linear = codeWithModuleBoilerplate(part1Code);
const linearBuffer = new Uint8Array(linear);
const module = await WebAssembly.compile(linearBuffer);
const instance = await WebAssembly.instantiate(module, importObj);
return { instance, integers };
}
Insert cell
modifiedCode = {
const modified = intCode.slice();
modified[1] = 12;
modified[2] = 2;
return modified;
}
Insert cell
step = {
const m = await buildModule(modifiedCode);
let location = 0;
while (location !== -1) {
yield { location, integers: m.integers };
location = m.instance.exports.x(location);
}
}
Insert cell
step.integers[0]
Insert cell
step.location
Insert cell
Insert cell
Insert cell
Insert cell
cols = 16
Insert cell
Insert cell
Insert cell
solve = async (noun, verb) => {
const modified = intCode.slice();
modified[1] = noun;
modified[2] = verb;

const m = await buildModule(modified);
let location = 0;
while (location !== -1) {
location = m.instance.exports.x(location);
}
return m.integers[0];
}
Insert cell
attempt = {
for (let noun = 0; noun < 100; noun++) {
for (let verb = 0; verb < 100; verb++) {
const result = await solve(noun, verb);
if (result === 19690720) {
yield { noun, verb, solution: noun * 100 + verb };
return;
}
if (verb === 0) {
yield { noun, verb, result };
}
}
}
}
Insert cell
Insert cell
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