Public
Edited
Dec 21
Paused
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
numericPad = padLookup(["789", "456", "123", " 0A"])
Insert cell
Insert cell
dirPad = padLookup([" ^A", "<v>"])
Insert cell
function padLookup(padRows) {
const coords = {};
const gap = padRows.length === 2 ? `0,0` : `3,0`;
padRows.forEach((keys, row) => {
[...keys].forEach((key, col) => {
if (key !== " ") {
coords[key] = [row, col];
}
});
});
return { coords, gap };
}
Insert cell
Insert cell
function shortestPath(key1, key2, pad) {
const [r1, c1] = pad.coords[key1];
const [r2, c2] = pad.coords[key2];

const ud = r2 > r1 ? "v".repeat(r2 - r1) : "^".repeat(r1 - r2);
const lr = c2 > c1 ? ">".repeat(c2 - c1) : "<".repeat(c1 - c2);

if (c2 > c1 && `${r2},${c1}` !== pad.gap) {
// Safe to move vertically first if heading right and corner point isn't the gap
return `${ud}${lr}A`;
}
if (`${r1},${c2}` !== pad.gap) {
// Safe to move horizontally first if corner point isn't the gap
return `${lr}${ud}A`;
}
// Must be safe to move vertically first because we can't be in same column as gap.
return `${ud}${lr}A`;
}
Insert cell
Insert cell
function sequences(seq, pad) {
const keys = [];
let prevKey = "A";
for (let key of seq) {
keys.push(shortestPath(prevKey, key, pad));
prevKey = key;
}
return keys;
}
Insert cell
Insert cell
function part1(input) {
const codes = input.split("\n");
const r1Seqs = codes.map((code) => sequences(code, numericPad).join(""));
const r2Seqs = r1Seqs.map((d) => sequences(d, dirPad).join(""));
const r3Seqs = r2Seqs.map((d) => sequences(d, dirPad).join(""));

return d3.sum(r3Seqs, (d, i) => d.length * Number(codes[i].slice(0, -1)));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function complexity(codes, numDirRobots = 25) {
// Frequency table of sub-sequences
const seqCounts = (seq) =>
sequences(seq, dirPad).reduce(
(fTable, s) => AOC.addToFreqTable(fTable, s),
new Map()
);

// Start with the numeric keypad sequences
let fTables = codes.map(
(code) => new Map([[sequences(code, numericPad).join(""), 1]])
);

// Expand sequences for each robot
for (let i = 0; i < numDirRobots; i++) {
fTables = fTables.map((fTable) => {
const subFTable = new Map();
fTable.forEach((freq, seq) =>
seqCounts(seq).forEach((subFreq, subSeq) =>
subFTable.set(subSeq, (subFTable.get(subSeq) || 0) + subFreq * freq)
)
);
return subFTable;
});
}

// Calculate the final complexity from each code's sequence frequencies
const cmplx = (seq) =>
d3.sum([...seq.entries()], ([key, freq]) => key.length * freq);

return d3.sum(
fTables,
(seq, i) => cmplx(seq) * Number(codes[i].slice(0, -1))
);
}
Insert cell
function part2(input) {
return complexity(input.split("\n"));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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