65 lines
2.1 KiB
D
65 lines
2.1 KiB
D
|
import std;
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
readText("input").calculateNumberOfContainingBagsTranisitively("shiny gold").writeln;
|
||
|
}
|
||
|
|
||
|
auto calculateNumberOfContainingBagsTranisitively(string rules, string color)
|
||
|
{
|
||
|
return rules.calculateContainingBagsTranisitively(color).byKey.count;
|
||
|
}
|
||
|
|
||
|
auto calculateContainingBagsTranisitively(string rules, string color)
|
||
|
{
|
||
|
return rules.parseRules.calculateContainingBagsTranisitively(color);
|
||
|
}
|
||
|
|
||
|
void[0][string] calculateContainingBagsTranisitively(string[][string] containedInMap, string color)
|
||
|
{
|
||
|
string[]* containingBags = (color in containedInMap);
|
||
|
if (!containingBags || (*containingBags).length == 0)
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
void[0][string] result;
|
||
|
foreach (bag; *containingBags)
|
||
|
{
|
||
|
result[bag] = [];
|
||
|
containedInMap.calculateContainingBagsTranisitively(bag)
|
||
|
.byKey.each!((containingBag) => result[containingBag] = []);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
auto parseRules(string rules)
|
||
|
{
|
||
|
string[][string] containedInMap;
|
||
|
rules.splitter("\n").filter!(not!empty)
|
||
|
.each!((rule) {
|
||
|
auto spec = rule.split(" bags contain ");
|
||
|
auto containingBag = spec[0];
|
||
|
spec[1].splitter(", ").filter!(it => it != "no other bags.")
|
||
|
.map!(bagSpec => bagSpec.matchFirst(r"(\d+) (.+) (bag|bags)\.*")[2])
|
||
|
.each!(bag => containedInMap.update(bag, {
|
||
|
return [containingBag];
|
||
|
}, (ref string[] old) { return old ~ [containingBag]; }));
|
||
|
});
|
||
|
return containedInMap;
|
||
|
}
|
||
|
|
||
|
unittest
|
||
|
{
|
||
|
auto input = `light red bags contain 1 bright white bag, 2 muted yellow bags.
|
||
|
dark orange bags contain 3 bright white bags, 4 muted yellow bags.
|
||
|
bright white bags contain 1 shiny gold bag.
|
||
|
muted yellow bags contain 2 shiny gold bags, 9 faded blue bags.
|
||
|
shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags.
|
||
|
dark olive bags contain 3 faded blue bags, 4 dotted black bags.
|
||
|
vibrant plum bags contain 5 faded blue bags, 6 dotted black bags.
|
||
|
faded blue bags contain no other bags.
|
||
|
dotted black bags contain no other bags.`;
|
||
|
|
||
|
assert(input.calculateNumberOfContainingBagsTranisitively("shiny gold") == 4);
|
||
|
}
|