jsadvent/solutions/2020/7.js
2020-12-10 02:33:00 -06:00

71 lines
1.8 KiB
JavaScript

const { Glib, Maps } = require('../../lib');
const parse = (input) =>
Glib.fromLines(input).map((line) => {
const [color, heldString] = line.split(' bags contain ');
const children = [];
if (heldString !== 'no other bags.') {
const helds = heldString.split(', ');
for (const held of helds) {
const [heldDef] = held.split(' bag');
const [heldNum, ...heldColorArr] = heldDef.split(' ');
const heldColor = heldColorArr.join(' ');
children.push({
count: BigInt(heldNum),
color: heldColor,
});
}
}
return { color, children };
});
const parseChildren = (input) =>
parse(input).reduce((map, { color, children }) => {
map.set(color, children);
return map;
}, new Map());
const parseParents = (input) =>
parse(input).reduce((map, { color: parentColor, children }) => {
for (const { color } of children) {
let parent;
map.set(color, (parent = map.get(color) || new Set()));
parent.add(parentColor);
}
return map;
}, new Map());
const childrenCount = (start, graph) => {
const children = graph.get(start) || [];
let count = BigInt(0);
for (const child of children) {
count += child.count;
count += childrenCount(child.color, graph) * child.count;
}
return count;
};
module.exports = {
'1': (input) => {
const parents = parseParents(input);
const found = new Set(parents.get('shiny gold'));
let lastCount = 0;
while (lastCount !== found.size) {
lastCount = found.size;
for (const color of found) {
for (const addedColor of parents.get(color) || []) {
found.add(addedColor);
}
}
}
return lastCount;
},
'2': (input) => {
return childrenCount('shiny gold', parseChildren(input));
},
};