49 lines
1.6 KiB
D
49 lines
1.6 KiB
D
|
import std;
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
readText("input").calculateNumberOfRequiredBags("shiny gold").writeln;
|
||
|
}
|
||
|
|
||
|
auto calculateNumberOfRequiredBags(string rules, string bag)
|
||
|
{
|
||
|
return rules.parseRules.calculateNumberOfRequiredBags(bag) - 1;
|
||
|
}
|
||
|
|
||
|
int calculateNumberOfRequiredBags(Tuple!(int, string)[][string] containmentMap, string bag)
|
||
|
{
|
||
|
return 1 + containmentMap[bag].map!(containedBag => containedBag[0]
|
||
|
* containmentMap.calculateNumberOfRequiredBags(containedBag[1])).sum;
|
||
|
}
|
||
|
|
||
|
auto parseRules(string rules)
|
||
|
{
|
||
|
Tuple!(int, string)[][string] containmentMap;
|
||
|
rules.splitter("\n").filter!(not!empty)
|
||
|
.each!((rule) {
|
||
|
auto spec = rule.split(" bags contain ");
|
||
|
containmentMap[spec[0]] = spec[1].splitter(", ").filter!(it => it != "no other bags.")
|
||
|
.map!((bagSpec) {
|
||
|
auto match = bagSpec.matchFirst(r"(\d+) (.+) (bag|bags)\.*");
|
||
|
return tuple(match[1].to!int, match[2]);
|
||
|
})
|
||
|
.array;
|
||
|
});
|
||
|
return containmentMap;
|
||
|
}
|
||
|
|
||
|
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.calculateNumberOfRequiredBags("shiny gold") == 32);
|
||
|
}
|