#!/bin/node const fs = require('fs'); fs.readFile('input.txt', (err, data) => { const rules = data.toString() .split('\n') .filter(rule => rule.length > 0) .map(rule => rule.split(" bags contain ")) .map(rule => [rule[0], rule[1].split(', ') .filter(line => !line.endsWith('no other bags.')) .map(line => line.replace(/ bags?\.?/, '')) .map(line => { const firstSpaceIndex = line.indexOf(' '); return { count: parseInt(line.substring(0, firstSpaceIndex)), bagColor: line.substring(firstSpaceIndex + 1), }; })]); const ruleMap = {}; for (const [containerColor, contents] of rules) { ruleMap[containerColor] = contents; } const matchingColors = []; let matchingColorsCount; do { matchingColorsCount = matchingColors.length; for (const [containerColor, contents] of rules) { if (matchingColors.indexOf(containerColor) < 0 && (contents.find(content => content.bagColor === 'shiny gold' || matchingColors.indexOf(content.bagColor) >= 0))) { matchingColors.push(containerColor); } } } while (matchingColorsCount !== matchingColors.length); function countBagsInBag(bagColor, bagCount) { const contents = ruleMap[bagColor]; return bagCount + bagCount * contents.reduce((sum, content) => sum + countBagsInBag(content.bagColor, content.count), 0); } console.log(matchingColors.length, countBagsInBag('shiny gold', 1) - 1); });