diff options
| -rw-r--r-- | challenge-270/bruce-gray/raku/ch-1.raku | 78 | ||||
| -rw-r--r-- | challenge-270/bruce-gray/raku/ch-2.raku | 42 |
2 files changed, 120 insertions, 0 deletions
diff --git a/challenge-270/bruce-gray/raku/ch-1.raku b/challenge-270/bruce-gray/raku/ch-1.raku new file mode 100644 index 0000000000..61b3697dcf --- /dev/null +++ b/challenge-270/bruce-gray/raku/ch-1.raku @@ -0,0 +1,78 @@ +sub task1_single_expression (@matrix) { + return @matrix».grep( :k, 1 ) + .grep( *.elems == 1 ) + .map( *.head ) + .Bag + .grep( *.value == 1 ) + .elems; +} +sub task1_original (@matrix) { + my BagHash $bh .= new; + for @matrix.kv -> $row_num, @row { + my $col_found; + for @row.kv -> $col_num, $cell { + if $cell == 1 { + if $col_found.defined { + $col_found = Nil; + last; + } + $col_found = $col_num; + } + } + if $col_found.defined { + $bh{$col_found}++; + } + } + return $bh.grep(*.value == 1).elems; +} +# Reducing by step-wise refactoring until we reach the single-expression version +sub task1_original_reduced_1 (@matrix) { + my BagHash $bh .= new; + for @matrix -> @row { + my @ones_locations = @row.grep(:k, 1); + $bh{ @ones_locations.head }++ if @ones_locations.elems == 1; + } + return $bh.grep(*.value == 1).elems; +} +sub task1_original_reduced_2 (@matrix) { + my BagHash $bh .= new; + for @matrix.map( *.grep(:k, 1) ) -> @ones_locations { + $bh{ @ones_locations.head }++ if @ones_locations.elems == 1; + } + return $bh.grep(*.value == 1).elems; +} +sub task1_original_reduced_3 (@matrix) { + my @column_numbers = gather for @matrix.map( *.grep(:k, 1) ) { + take .head if .elems == 1; + } + my Bag $b .= new(@column_numbers); + return $b.grep(*.value == 1).elems; +} +sub task1_original_reduced_4 (@matrix) { + my @column_numbers = @matrix.map( *.grep(:k, 1) ).grep(*.elems == 1).map(*.head); + return @column_numbers.Bag.grep(*.value == 1).elems; +} +sub task1_original_reduced_5 (@matrix) { + return @matrix.map( *.grep(:k, 1) ).grep(*.elems == 1).map(*.head).Bag.grep(*.value == 1).elems; +} + + +constant @subs = + :&task1_single_expression, + :&task1_original, + :&task1_original_reduced_1, + :&task1_original_reduced_2, + :&task1_original_reduced_3, + :&task1_original_reduced_4, + :&task1_original_reduced_5, +; +constant @tests = + ( 1, ( (1, 0, 0), (0, 0, 1), (1, 0, 0) ) ), + ( 3, ( (1, 0, 0), (0, 1, 0), (0, 0, 1) ) ), +; +use Test; plan +@tests * +@subs; +for @subs -> ( :key($sub_name), :value(&task1) ) { + for @tests -> ($expected, @matrix) { + is task1(@matrix), $expected, "$sub_name : @matrix[]"; + } +} diff --git a/challenge-270/bruce-gray/raku/ch-2.raku b/challenge-270/bruce-gray/raku/ch-2.raku new file mode 100644 index 0000000000..4562c50bc9 --- /dev/null +++ b/challenge-270/bruce-gray/raku/ch-2.raku @@ -0,0 +1,42 @@ +sub task2 ( $level1cost, $level2cost, @ns is copy --> UInt ) { + if ($level1cost, $level2cost).any < 0 { + die "Negative cost is not explicitly forbidden by the task description, but I will not guarantee my algorithm is optimal if negative cost is allowed"; + } + my $target = @ns.max; + + my $level_one_will_always_be_cheaper = ( $level2cost >= 2*$level1cost ); + if $level_one_will_always_be_cheaper { + my @distances_to_maximum = $target X- @ns; + return @distances_to_maximum.sum * $level1cost; + } + + my $cost = 0; + until @ns < 2 or @ns.all == $target { + @ns .= sort(+*); + pop @ns while @ns and @ns.tail == $target; + if @ns >= 2 and @ns.head(2).all < $target { + $cost += $level2cost; + @ns[0]++; + @ns[1]++; + } + } + # Now either 0 or 1 elements of @ns can remain. + if @ns { + if @ns == 1 { + $cost += ($level1cost * ($target - @ns.head) ); + } + else { + die "Cannot happen"; + } + } + + return $cost; +} +use Test; plan +constant @tests = + # $expected, $x, $y, @ints + ( 9, 3, 2, (4, 1) ), + ( 6, 2, 1, (2, 3, 3, 3, 5) ), +; +for @tests -> ($expected, $x, $y, @ns) { + is task2($x, $y, @ns), $expected, "X($x) Y($y) INT(@ns[])"; +} |
