let input = Deno.readTextFileSync("input.dat").split("\n")
input.pop() // remove empty final value
const rules = {}
for (let line of input) {
const contents = []
const [outerColor, contentsStr] = line.split(" bags contain ")
const contentsArr = contentsStr.split(", ").filter(s => s !== "no other bags.")
for (let content of contentsArr) {
const [, count, color] = /^(\d) (.*) bag/.exec(content)
contents.push({color, count: Number(count)})
}
rules[outerColor] = contents
}
function partOne(rules, target) {
const goodColors = []
for (let [outerColor, contents] of Object.entries(rules)) {
while (contents.length) {
if (contents.some(bag => bag.color === target)) {
goodColors.push(outerColor)
break
}
let newContents = []
for (let { color } of contents) {
newContents = newContents.concat(rules[color])
}
contents = newContents
}
}
return [...new Set(goodColors)].length
}
function partTwo(rules, target) {
let total = 0
let contents = rules[target]
while (contents.length) {
let newContents = []
for (let { color, count } of contents) {
total += count
let newBags = rules[color].map(newBag => ({count: newBag.count * count, color: newBag.color}))
newContents = newContents.concat(newBags)
}
contents = newContents
}
return total
}
console.log("part one:", partOne(rules, "shiny gold"))
console.log("part two:", partTwo(rules, "shiny gold"))