AoC 2021 D18: Snailfish

TypeScript | Problem statement | Source code | Tags: Data structures

← Previous Back to AoC Index Next →

Part 1

The first barrier was how to parse the input. Lucky for me, this is valid JSON, so I could just use JSON.parse. I wonder what happens if I use C++.

The next challenge was how to represent snailfish numbers. I went with the most straightforward approach: a binary tree where each node is either a pair (with left and right children) or a regular number (a leaf node). Since we later need upward traversal during explosion, I also stored a parent pointer.

type SnailNumPair = {
type: "pair";
left: SnailNum;
right: SnailNum;
parent: SnailNumPair | null;
};
type SnailNumNum = { type: "num"; value: number; parent: SnailNumPair | null };
type SnailNum = SnailNumPair | SnailNumNum;
ts

Building the tree from the parsed JSON is just a matter of "inflating" each level of arrays into objects.

function buildSnailNum(obj: InputNum): SnailNum {
if (typeof obj === "number") {
return { type: "num", value: obj, parent: null };
}
const pair: SnailNumPair = {
type: "pair",
left: buildSnailNum(obj[0]),
right: buildSnailNum(obj[1]),
parent: null,
};
pair.left.parent = pair;
pair.right.parent = pair;
return pair;
}
ts

My code for explode is just a huge spaghetti. The signature is function explode(a: SnailNum, depth: number): boolean, which returns whether an explosion happened.

As for split, the idea is similar.

Once we have explode and split, add is straightforward.

function add(a: SnailNum, b: SnailNum): SnailNum {
const p: SnailNumPair = { type: "pair", left: a, right: b, parent: null };
a.parent = p;
b.parent = p;
while (true) {
if (explode(p, 0)) continue;
if (split(p)) continue;
break;
}
return p;
}
ts

In part 1, we just need to add them up:

const res = nums.slice(1).reduce((acc, curr) => {
const currNum = buildSnailNum(curr);
return add(acc, currNum);
}, buildSnailNum(nums[0]));
ts

Part 2

In part 2, we just pairwise add all snailfish numbers and compute the maximum magnitude.

let maxMag = 0;
for (const a of nums) {
for (const b of nums) {
if (a === b) continue;
const sum = add(buildSnailNum(a), buildSnailNum(b));
const mag = magnitude(sum);
if (mag > maxMag) {
maxMag = mag;
}
}
}
ts

← Previous Back to AoC Index Next →