Published
Edited
Dec 8, 2021
1 star
Insert cell
Insert cell
Insert cell
{
let uniqueLengths = [1, 4, 7, 8]
return uniqueLengths.reduce((accumulator, currentValue, index, array) => {
return accumulator + lengths[digitToLength.get(currentValue) - 1]
}, 0)
}
Insert cell
digitToLength = new Map([
[0, 6],
[1, 2],
[2, 5],
[3, 5],
[4, 4],
[5, 5],
[6, 6],
[7, 3],
[8, 7],
[9, 6],
])
Insert cell
lengths = input.reduce((accumulator, currentValue, index, array) => {
currentValue.get("output").forEach( digit => {
let l = digit.size
accumulator[l-1]++
})
return accumulator
}, new Array(7).fill(0))
Insert cell
Insert cell
connections = inferConnections(input[0].get("signals"))
Insert cell
input.map( reading => {
let connections = inferConnections(reading.get("signals"))
let number = parseFloat(reading.get("output")
.map( digit => readDigit(digit, connections))
.join("")
)
return number
})
.reduce( (acc, curr) => acc + curr)
Insert cell
function inferConnections(signals) {
let possibleAssociations = new Map([
['a', new Set(['e','g'])],
['b', new Set(['e','g'])],
['c', new Set(['e','g'])],
['d', new Set(['e','g'])],
['e', new Set(['e','g'])],
['f', new Set(['e','g'])],
['g', new Set(['e','g'])]
])

// get the "1" signal
let one = signals.filter( signal => signal.size == 2)[0]
possibleAssociations.forEach( (associations, wire) => {
if (one.has(wire))
possibleAssociations.set(wire, new Set(["c", "f"])) // override the default values
})

// get the "7" signal
let seven = signals.filter( signal => signal.size == 3)[0]
possibleAssociations.forEach( (associations, wire) => {
if (seven.has(wire) && !associations.has("c"))
possibleAssociations.set(wire, new Set(["a"])) // override the default values
})

// get the "4" signal
let four = signals.filter( signal => signal.size == 4)[0]
possibleAssociations.forEach( (associations, wire) => {
if (four.has(wire) && !associations.has("c"))
possibleAssociations.set(wire, new Set(["b", "d"])) // override the default values
})

// digits of size 5 (2,3,5) will lack wires "b" and "e" twice
let sizeFive = signals.filter( signal => signal.size == 5)
let allWires = new Set(["a","b","c","d","e","f","g"])
sizeFive.map( signal => Array.from(setDifference(allWires, signal)))
.flat()
.reduce( (acc, curr) => {
if (acc.has(curr))
acc.set(curr, acc.get(curr) + 1)
else
acc.set(curr, 1)
return acc
}, new Map())
.forEach( (count, wire) => {
if (count === 2) {
let prevAssoc = possibleAssociations.get(wire)
prevAssoc.delete("d") // if it is "b", remove it's ambiguity with "d"
prevAssoc.delete("g") // if it is "e", remove it's ambiguity with "g"
possibleAssociations.set(wire, prevAssoc)
}
})
// now remove "b" and "e" from "d" and "g"
possibleAssociations.forEach( (associations, wire) => {
if (associations.has("d"))
possibleAssociations.set(wire, new Set(["d"]))
if (associations.has("g"))
possibleAssociations.set(wire, new Set(["g"]))
})

// digits of size 6 (0,6,9) will lack wires "d", "c" and "e"
// since we know which wires go to "d" and "e", the only one with two possible connections is the one to "c"
let sizeSix = signals.filter( signal => signal.size == 6)
let wireToC = sizeSix.map( signal => Array.from(setDifference(allWires, signal)))
.flat()
.filter( wire => possibleAssociations.get(wire).size === 2)[0]
possibleAssociations.set(wireToC, new Set(["c"]))
possibleAssociations.forEach( (associations, wire) => {
if (associations.has("f"))
possibleAssociations.set(wire, new Set(["f"]))
})

// convert sets to a single value
possibleAssociations.forEach( (association, wire) => {
possibleAssociations.set(wire, Array.from(association)[0])
})
return possibleAssociations
}
Insert cell
function readDigit( digit, connectionTable ) {
let segmentsToDigit = new Map([
["abcefg", 0],
["cf", 1],
["acdeg", 2],
["acdfg", 3],
["bcdf", 4],
["abdfg", 5],
["abdefg", 6],
["acf", 7],
["abcdefg", 8],
["abcdfg", 9]
])

return segmentsToDigit.get(Array.from(digit).map( wire => connectionTable.get(wire)).sort().join(""))
}
Insert cell
function setDifference (setA, setB) {
var difference = new Set(setA);
for (var elem of setB) {
difference.delete(elem);
}
return difference;
}
Insert cell
Insert cell
testData = preProcessInput(testInput)
Insert cell
Insert cell
input = FileAttachment("08_input.txt").text().then( txt => preProcessInput(txt))
Insert cell
function preProcessInput(txt) {
return txt.trim().split("\n").map( line => {
let parts = line.split("|")
let signals = parts[0].trim().split(" ").map( signal => new Set(signal.split("").sort()))
let digitsOutput = parts[1].trim().split(" ").map( signal => new Set(signal.split("").sort()))
return new Map([['signals', signals], ['output', digitsOutput]])
})
}
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