Notebooks 2.0 is here.

Published
Edited
Dec 16, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function valuator(node) {
const processor = processors[node.type];
return processor.engine(node, valuator, processor.reducer)
}
Insert cell
Insert cell
processors = [
// ID: 0
{engine: aggregate, reducer: (s, i) => s + i},
// ID: 1
{engine: aggregate, reducer: (p, i) => p * i},
// ID: 2
{engine: aggregate, reducer: (a, b) => a < b ? a : b},
// ID: 3
{engine: aggregate, reducer: (a, b) => a > b ? a : b},
// ID: 4
{engine: value, reducer: (node) => node.value},
// ID: 5
{engine: difference, reducer: -1},
// ID: 6
{engine: difference, reducer: +1},
// ID: 7
{engine: difference, reducer: 0},
]
Insert cell
// takes a node, valuator, and reducer
// returns aggregate value obtained by applying reducer on all sub-packets
aggregate = (node, value, reducer) => d3.reduce(node.packets.map(value), reducer)
Insert cell
// takes a node
// returns its value
value = (node, value, reducer) => reducer(node)
Insert cell
// takes a node and expected difference (-1, -, +1)
// returns 1n if actual matches expected, 0n otherwise
difference = (node, value, expected) => diff(value(node.packets[0]), value(node.packets[1])) === expected ? 1n : 0n
Insert cell
// takes two numbers
// returns -1, 0, or +1 as a function of (b - a)
diff = (a, b) => (b - a) < 0 ? -1 : (b - a) > 0 ? +1 : 0 // Math.sign() fails on BigInt
Insert cell
Insert cell
parsed = packet(test)
Insert cell
function* versions(p) {
yield p.version;
for (const s of p.packets || []) yield* versions(s);
}
Insert cell
function packet(s) {
const b = typeof s === "string" ? bits(s) : s;
const version = takeInt(b, 3);
const type = takeInt(b, 3);
if (type === 4) {
// literal
let value = 0n;
let prefix;
do {
prefix = takeInt(b, 1);
value = (value << 4n) | BigInt(takeInt(b, 4));
} while (prefix);
return { version, type, value };
} else {
// operator
const packets = [];
const lengthType = takeInt(b, 1);
if (lengthType === 0) {
const size = takeInt(b, 15);
const sub = take(b, size);
for (let p; (p = packet(sub)); ) packets.push(p);
return { version, type, packets, lengthType, size };
} else if (lengthType === 1) {
const n = takeInt(b, 11);
for (let i = 0; i < n; i++) packets.push(packet(b));
return { version, type, packets, lengthType, n };
}
}
}
Insert cell
takeInt = (iterable, n) => parseInt([...take(iterable, n)].join(""), 2)
Insert cell
function* take(iterable, n) {
while (n--) yield iterable.next().value;
}
Insert cell
function* bits(string) {
for (const c of string) yield* parseInt(c, 16).toString(2).padStart(4, "0");
}
Insert cell
input = realPuzzleInput
Insert cell
realPuzzleInput = `005473C9244483004B001F79A9CE75FF9065446725685F1223600542661B7A9F4D001428C01D8C30C61210021F0663043A20042616C75868800BAC9CB59F4BC3A40232680220008542D89B114401886F1EA2DCF16CFE3BE6281060104B00C9994B83C13200AD3C0169B85FA7D3BE0A91356004824A32E6C94803A1D005E6701B2B49D76A1257EC7310C2015E7C0151006E0843F8D000086C4284910A47518CF7DD04380553C2F2D4BFEE67350DE2C9331FEFAFAD24CB282004F328C73F4E8B49C34AF094802B2B004E76762F9D9D8BA500653EEA4016CD802126B72D8F004C5F9975200C924B5065C00686467E58919F960C017F00466BB3B6B4B135D9DB5A5A93C2210050B32A9400A9497D524BEA660084EEA8EF600849E21EFB7C9F07E5C34C014C009067794BCC527794BCC424F12A67DCBC905C01B97BF8DE5ED9F7C865A4051F50024F9B9EAFA93ECE1A49A2C2E20128E4CA30037100042612C6F8B600084C1C8850BC400B8DAA01547197D6370BC8422C4A72051291E2A0803B0E2094D4BB5FDBEF6A0094F3CCC9A0002FD38E1350E7500C01A1006E3CC24884200C46389312C401F8551C63D4CC9D08035293FD6FCAFF1468B0056780A45D0C01498FBED0039925B82CCDCA7F4E20021A692CC012B00440010B8691761E0002190E21244C98EE0B0C0139297660B401A80002150E20A43C1006A0E44582A400C04A81CD994B9A1004BB1625D0648CE440E49DC402D8612BB6C9F5E97A5AC193F589A100505800ABCF5205138BD2EB527EA130008611167331AEA9B8BDCC4752B78165B39DAA1004C906740139EB0148D3CEC80662B801E60041015EE6006801364E007B801C003F1A801880350100BEC002A3000920E0079801CA00500046A800C0A001A73DFE9830059D29B5E8A51865777DCA1A2820040E4C7A49F88028B9F92DF80292E592B6B840`
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