|
| 1 | +const input = (await Deno.readTextFile("/dev/stdin")); |
| 2 | + |
| 3 | +type Bag = { |
| 4 | + color: string; |
| 5 | + bags_inside: BagRef[]; |
| 6 | +}; |
| 7 | +type BagRef = { |
| 8 | + count: number; |
| 9 | + color: string; |
| 10 | +}; |
| 11 | + |
| 12 | +const bags = [ |
| 13 | + ...input.matchAll(/([\w]+ [\w]+) bags contain (\d (.*)[.]|no other bags)/g), |
| 14 | +].map(([, color, rest]) => { |
| 15 | + const bags_inside = ([ |
| 16 | + ...rest.matchAll(/(\d) ([\w]+ [\w]+)/g), |
| 17 | + ]) |
| 18 | + .map(([, count, color]) => ({ count: parseInt(count), color })) as BagRef[]; |
| 19 | + |
| 20 | + return ({ color, bags_inside }); |
| 21 | +}) as Bag[]; |
| 22 | + |
| 23 | +const COLOR_SHINY_GOLD = "shiny gold"; |
| 24 | + |
| 25 | +// --- Part 1 ---- |
| 26 | +// Recursively find shiny golden bags |
| 27 | +function findShinyGoldenBag(bag_refs: BagRef[]) { |
| 28 | + if (bag_refs.length === 0) { |
| 29 | + return 0; |
| 30 | + } |
| 31 | + |
| 32 | + const resolved_bags = bag_refs |
| 33 | + .map((bag) => bags.find(({ color }) => color === bag.color)) |
| 34 | + .filter((bag) => bag !== undefined) as Bag[]; |
| 35 | + |
| 36 | + for (const { color, bags_inside } of resolved_bags) { |
| 37 | + if (color === COLOR_SHINY_GOLD) { |
| 38 | + return 1; |
| 39 | + } else { |
| 40 | + const found = findShinyGoldenBag(bags_inside); |
| 41 | + if (found) { |
| 42 | + return 1; |
| 43 | + } else { |
| 44 | + continue; |
| 45 | + } |
| 46 | + } |
| 47 | + } |
| 48 | + return 0; |
| 49 | +} |
| 50 | + |
| 51 | +const bagContainingShinyGoldeBagCount = bags |
| 52 | + .reduce((count, bag) => count + findShinyGoldenBag(bag.bags_inside), 0); |
| 53 | + |
| 54 | +// --- Part 2 --- |
| 55 | +// Recursively count bags inside |
| 56 | +function countBagsInside(bag_refs: BagRef[]): number { |
| 57 | + if (bag_refs.length === 0) { |
| 58 | + return 1; |
| 59 | + } |
| 60 | + |
| 61 | + const resolved_bags = bag_refs |
| 62 | + .map( |
| 63 | + (bag) => [bag.count, bags.find(({ color }) => color === bag.color)] |
| 64 | + ) as [number, Bag][]; |
| 65 | + |
| 66 | + const count = resolved_bags |
| 67 | + .reduce( |
| 68 | + (acc, [bag_count, bag]) => |
| 69 | + acc + bag_count * countBagsInside(bag.bags_inside), |
| 70 | + 1, |
| 71 | + ); |
| 72 | + |
| 73 | + return count; |
| 74 | +} |
| 75 | + |
| 76 | +const shinyGoldenBag = bags.find(({ color }) => |
| 77 | + color === COLOR_SHINY_GOLD |
| 78 | +) as Bag; |
| 79 | + |
| 80 | +const shinyGoldBagInsideCount = countBagsInside(shinyGoldenBag.bags_inside) - 1; |
| 81 | + |
| 82 | +console.log(`${bagContainingShinyGoldeBagCount}`); |
| 83 | +console.log(`${shinyGoldBagInsideCount}`); |
0 commit comments