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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more