const fs = require('fs'); const OWN_BAG = 'shiny gold'; function parseLine(line) { let [ self, others ] = line.trim().split(" bags contain "); if (self === undefined || others === undefined) return []; if (others == "no other bags.") return []; // [{a: self, b: null, count: 0}]; others = others.replace(".", "").replace(/bags?/g, "").split(","); return others.map((other) => { let [ num, ...rest ] = other.trim().split(' '); return { a: self, b: rest.join(' '), count: Number(num) }; }); } fs.readFile('input', (err, data) => { if (err) throw err; let rules = data.toString().split("\n").map( parseLine ).flat(); let bags = {}; rules.forEach((rule) => { let parent = bags[rule.a] || {spec: rule.a}; let child = bags[rule.b] || {spec: rule.b}; if (!child.hasOwnProperty('parent')) child.parent = parent; if (!parent.hasOwnProperty('children')) parent.children = []; parent.children.push({ count: rule.count, bag: child }); bags[rule.a] = parent; bags[rule.b] = child; }); let bagCount = function(bag, self_count) { if (!bag.children) return self_count; return self_count + (bag.children.map((node) => bagCount(node.bag, node.count)).reduce((a,b) => a+b) * self_count); }; let result = bags[OWN_BAG].children.map((node) => bagCount(node.bag, node.count)).reduce((a,b) => (a+b)); console.log(result); });