Published
Edited
Dec 16, 2021
Insert cell
Insert cell
Insert cell
sumPacketVersions(decodePackets(input)[0])
Insert cell
function sumPacketVersions(packet) {
let sum = readBinary(packet.version)
if (Array.isArray(packet.content)) {
for (let subPacket of packet.content) {
sum += sumPacketVersions(subPacket)
}
}
return sum
}
Insert cell
Insert cell
evalPacket(decodePackets(input)[0])
Insert cell
function evalPacket(packet) {
switch(packet.typeID) {
case "100": //4, literal value
return readBinary(packet.content)
break
case "000": //0, sum
return packet.content.reduce( (acc, curr) => acc + evalPacket(curr), 0)
break
case "001": //1, product
return packet.content.reduce( (acc, curr) => acc * evalPacket(curr), 1)
break
case "010": //2, min
return packet.content.reduce( (acc, curr) => Math.min(acc, evalPacket(curr)), Infinity)
break
case "011": //3, max
return packet.content.reduce( (acc, curr) => Math.max(acc, evalPacket(curr)), -Infinity)
break
case "101": //5, greater than
return evalPacket(packet.content[0]) > evalPacket(packet.content[1]) ? 1 : 0
break
case "110": //6, less than
return evalPacket(packet.content[0]) < evalPacket(packet.content[1]) ? 1 : 0
break
case "111": //7, equal to
return evalPacket(packet.content[0]) === evalPacket(packet.content[1]) ? 1 : 0
break
}
}
Insert cell
Insert cell
function decodePackets(transmission, packetStart = 0) {
// read header
let version = transmission.substring(packetStart, packetStart + 3)
let typeID = transmission.substring(packetStart + 3, packetStart + 6)
let decodedPacket = {
version: version,
typeID: typeID,
content: null
}
let packetLength = 6 // header size
switch(typeID) {
case "100": // 4, literal value
let literal = ""
let groupStart = packetStart + 6
let continueReadingLiteral = true
let group = null
while (continueReadingLiteral) {
group = transmission.substring(groupStart, groupStart + 5)
let continuationBit = group[0]
literal += group.substring(1)
if (continuationBit === "0")
continueReadingLiteral = false
else {
groupStart += 5
}
}

decodedPacket.content = literal
packetLength += (groupStart + 5) - packetStart - 6 // do not count the header twice
break
default: // other than 4, operator
let lengthTypeID = transmission[packetStart + 6]
if (lengthTypeID === "0") {
// next 15 bits are the total length in bits of the sub-packets
let subPacketsLength = readBinary(transmission.substring(packetStart + 7, packetStart + 7 + 15))
let processedBits = 0
decodedPacket.content = []
while (processedBits < subPacketsLength) {
let [subPacket, subPacketLength] = decodePackets(transmission, packetStart + 7 + 15 + processedBits)
processedBits += subPacketLength
decodedPacket.content.push(subPacket)
}
packetLength += 1 + 15 + subPacketsLength
} else {
// next 11 bits are the number of sub-packets immediately contained
let subPacketsNumber = readBinary(transmission.substring(packetStart + 7, packetStart + 7 + 11))
let processedPackets = 0
let subPacketsTotalLength = 0
decodedPacket.content = []
while (processedPackets < subPacketsNumber) {
let [subPacket, subPacketLength] = decodePackets(transmission, packetStart + 7 + 11 + subPacketsTotalLength)
processedPackets++
subPacketsTotalLength += subPacketLength
decodedPacket.content.push(subPacket)
}
packetLength += 1 + 11 + subPacketsTotalLength
}
}
// also return the packet length to deal with the lengthTypeID == 0
return [decodedPacket, packetLength]
}
Insert cell
function readBinary(bin) {
return bin.split("").reverse().map( (bit, idx) => parseFloat(bit) * 2 ** idx).reduce( (acc, curr) => acc + curr)
}
Insert cell
Insert cell
Insert cell
test = readInput(`1238466168AF`)
Insert cell
input = FileAttachment("16_input.txt").text().then( txt => readInput(txt))
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