aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-270/bruce-gray/raku/ch-1.raku78
-rw-r--r--challenge-270/bruce-gray/raku/ch-2.raku42
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[])";
+}