diff options
Diffstat (limited to '2020/day-07/day-07.raku')
-rwxr-xr-x | 2020/day-07/day-07.raku | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/2020/day-07/day-07.raku b/2020/day-07/day-07.raku new file mode 100755 index 0000000..327a78b --- /dev/null +++ b/2020/day-07/day-07.raku @@ -0,0 +1,67 @@ +#!/usr/bin/env raku + +sub MAIN ( + Int $part where * == 1|2 = 1 #= part to run (1 or 2) +) { + my %bag; + my Int $count = 0; + my @valid_bags = "shiny gold",; + + for "input".IO.lines -> $entry { + if $entry ~~ /^(.*) \s bags \s contain (.*)./ -> $match { + my $bag = $match[0]; + for $match[1].split(", ") { + if $_ ~~ /(\d) \s (.*) \s bag/ -> $contain_bag { + push %bag{$bag}, { + count => $contain_bag[0].Int, + bag => $contain_bag[1].Str + }; + } + } + } + } + + if $part == 1 { + MAIN: while True { + my $previous_count = $count; + for keys %bag { + for @(%bag{$_}) -> $contain { + push @valid_bags, $_ if @valid_bags ∋ $contain<bag>; + } + } + + $count = 0; + COUNT: for keys %bag { + for @(%bag{$_}) -> $contain { + if @valid_bags ∋ $contain<bag> { + $count++; + next COUNT; + } + } + } + last MAIN if $previous_count == $count; + } + } elsif $part == 2 { + $count = count-bags(%bag, 'shiny gold'); + } + say "Part $part: ", $count; +} + +# count-bags takes %bag & the bag for which we have to count the bags +# & returns the count. Count here means the number of bags that will +# be inside $bag. +sub count-bags ( + %bag, Str $bag --> Int # count will be an integer. +) { + return 0 unless %bag{$bag}; + my Int $count = 0; + + for @(%bag{$bag}) { + my $sub_bags = count-bags(%bag, $_<bag>); + $count += $_<count>; + unless $sub_bags == 0 { + $count += $_<count> * $sub_bags; + } + } + return $count; +} |