diff options
| -rw-r--r-- | challenge-258/mark-anderson/raku/ch-1.raku | 6 | ||||
| -rw-r--r-- | challenge-258/mark-anderson/raku/ch-2.raku | 75 |
2 files changed, 81 insertions, 0 deletions
diff --git a/challenge-258/mark-anderson/raku/ch-1.raku b/challenge-258/mark-anderson/raku/ch-1.raku new file mode 100644 index 0000000000..a0d78a080c --- /dev/null +++ b/challenge-258/mark-anderson/raku/ch-1.raku @@ -0,0 +1,6 @@ +#!/usr/bin/env raku +use Test; + +is (10,1,111,24,1000).grep(*.chars %% 2).elems, 3; +is (111,1,11111) .grep(*.chars %% 2).elems, 0; +is (2,8,1024,256) .grep(*.chars %% 2).elems, 1; diff --git a/challenge-258/mark-anderson/raku/ch-2.raku b/challenge-258/mark-anderson/raku/ch-2.raku new file mode 100644 index 0000000000..3cdcc4fd35 --- /dev/null +++ b/challenge-258/mark-anderson/raku/ch-2.raku @@ -0,0 +1,75 @@ +#!/usr/bin/env raku +use Test; + +is sum-of-values([2,5,9,11,3], 1), 17; +is sum-of-values([2,5,9,11,3], 2), 11; +is sum-of-values([2,5,9,11,3], 0), 2; +is sum-of-values([^100], 4), 1555; +is sum-of-values([99...0], 4), 1019; +is sum-of-values([^1e6], 8), 52104319732; + +sub postfix:<!>($n) { [*] 1..$n } + +sub sum-of-values(@ints, $k) +{ + my $end = @ints.end; + + loop + { + last if $end.base(2) ~~ m:g/1/ == $k; + $end-- + } + + my $rank = rank($end.base(2)); + my $chars = $end.base(2).chars; + my @ones = 1 xx $chars; + my $combs = $chars-$k; + + return @ints[$end] unless $combs; + + my $channel = Channel.new; + + for ^$chars .combinations($combs) + { + last if $++ == $rank; + $channel.send($_) + } + + $channel.close; + + my @promises = gather for ^$*KERNEL.cpu-cores + { + take start process() + } + + await @promises; + + return sum @promises.map(*.result); + + sub process + { + sum gather while $channel.poll -> $combination + { + my @a = @ones; + $combination.map({ @a[$_] = 0 }); + my $i = ([~] @a).parse-base(2); + take @ints[$i] + } + } +} + +sub rank($s) +{ + my @a = $s.comb; + my @ranks = @a.sort.squish.antipairs.Map{@a}>>.succ; + my $bag = @ranks.BagHash; + + my @n = gather for @ranks -> $r + { + my @less-than = $bag.keys.grep(* < $r); + take ([+] $bag{@less-than}) / ([*] $bag.values>>!); + $bag{$r}-- + } + + 1 + [+] @n Z* (@ranks.end...0)>>! +} |
