This is my response to The Weekly Challenge #338.
m x n
matrix.
Input: @matrix = ([4, 4, 4, 4],
[10, 0, 0, 0],
[2, 2, 2, 9])
Output: 16
Row 1: 4 + 4 + 4 + 4 => 16
Row 2: 10 + 0 + 0 + 0 => 10
Row 3: 2 + 2 + 2 + 9 => 15
Example 2:
Input: @matrix = ([1, 5],
[7, 3],
[3, 5])
Output: 10
Example 3:
Input: @matrix = ([1, 2, 3],
[3, 2, 1])
Output: 6
Example 4:
Input: @matrix = ([2, 8, 7],
[7, 1, 3],
[1, 9, 5])
Output: 17
Example 5:
Input: @matrix = ([10, 20, 30],
[5, 5, 5],
[0, 100, 0],
[25, 25, 25])
Output: 100
#! /usr/bin/env raku
unit sub MAIN ($matrix, :v(:$verbose)); # [1]
my @matrix = $matrix.split("|")>>.words>>.Numeric; # [2]
die "Uneven row length" unless [==] @matrix>>.elems; # [3]
die "Non numeric value(s) in the matrix"
unless all(@matrix[*;*]) ~~ Numeric; # [4]
my @sum = @matrix>>.sum; # [5]
say ": Row sums: { @sum.join(",") }" if $verbose; # [6]
say @sum.max; # [7]
[1] Note the use of my «Matrix as a string» input syntax. See «Running it» below for sample usage.
[2] Unpack the matrix. Note that the coercion of the values to Numeric
is lazy,
so does not blow up right away if we supply non-numeric input. (That will happen in [4],
when the values are evaluated.)
[3] Ensure that all the rows have the same
number of elements, using the Reduction Metaoperator []
with ==
on all the row lengths (@matrix>>.elems
).
See
docs.raku.org/language/operators#Reduction_metaoperators for more
information about the Reduction Metaoperator []
.
[4] Ensure that we got Numeric
values only.
[5] Get the sum of each row.
[6] Print the row sums, if requested.
[7] Print the highest row sum.
Running it:
$ ./highest-row "4 4 4 4 | 10 0 0 0 | 2 2 2 9"
16
$ ./highest-row "1 5 | 7 3 | 3 5"
10
$ ./highest-row "1 2 3 | 3 2 1"
6
$ ./highest-row "2 8 7 | 7 1 3 | 1 9 5"
17
$ ./highest-row "10 20 30 | 5 5 5 | 0 100 0 | 25 25 25"
100
Looking good.
With verbose mode:
$ ./highest-row -v "4 4 4 4 | 10 0 0 0 | 2 2 2 9"
: Row sums: 16,10,15
16
$ ./highest-row -v "1 5 | 7 3 | 3 5"
: Row sums: 6,10,8
10
$ ./highest-row -v "1 2 3 | 3 2 1"
: Row sums: 6,6
6
$ ./highest-row -v "2 8 7 | 7 1 3 | 1 9 5"
: Row sums: 17,11,15
17
$ ./highest-row -v "10 20 30 | 5 5 5 | 0 100 0 | 25 25 25"
: Row sums: 60,15,100,75
100
Note that I have not made any check on the number of rows or columns, so this is valid:
./highest-row ""
0
As is this, but now we er are getting silly...
$ ./highest-row "| | | | | "
0
@arr1
and @arr2
.
Input: @arr1 = (4, 5, 7)
@arr2 = (9, 1, 3, 4)
Output: 6
With element $arr1[0] = 4
| 4 - 9 | = 5
| 4 - 1 | = 3
| 4 - 3 | = 1
| 4 - 4 | = 0
max distance = 5
With element $arr1[1] = 5
| 5 - 9 | = 4
| 5 - 1 | = 4
| 5 - 3 | = 2
| 5 - 4 | = 1
max distance = 4
With element $arr1[2] = 7
| 7 - 9 | = 2
| 7 - 1 | = 6
| 7 - 3 | = 4
| 7 - 4 | = 4
max distance = 6
max (5, 6, 6) = 6
Example 2:
Input: @arr1 = (2, 3, 5, 4)
@arr2 = (3, 2, 5, 5, 8, 7)
Output: 6
With element $arr1[0] = 2
| 2 - 3 | = 1
| 2 - 2 | = 0
| 2 - 5 | = 3
| 2 - 5 | = 3
| 2 - 8 | = 6
| 2 - 7 | = 5
max distance = 6
With element $arr1[1] = 3
| 3 - 3 | = 0
| 3 - 2 | = 1
| 3 - 5 | = 2
| 3 - 5 | = 2
| 3 - 8 | = 5
| 3 - 7 | = 4
max distance = 5
With element $arr1[2] = 5
| 5 - 3 | = 2
| 5 - 2 | = 3
| 5 - 5 | = 0
| 5 - 5 | = 0
| 5 - 8 | = 3
| 5 - 7 | = 2
max distance = 3
With element $arr1[3] = 4
| 4 - 3 | = 1
| 4 - 2 | = 2
| 4 - 5 | = 1
| 4 - 5 | = 1
| 4 - 8 | = 4
| 4 - 7 | = 3
max distance = 4
max (5, 6, 3, 4) = 6
Example 3:
Input: @arr1 = (2, 1, 11, 3)
@arr2 = (2, 5, 10, 2)
Output: 9
With element $arr1[0] = 2
| 2 - 2 | = 0
| 2 - 5 | = 3
| 2 - 10 | = 8
| 2 - 2 | = 0
max distance = 8
With element $arr1[1] = 1
| 1 - 2 | = 1
| 1 - 5 | = 4
| 1 - 10 | = 9
| 1 - 2 | = 1
max distance = 9
With element $arr1[2] = 11
| 11 - 2 | = 9
| 11 - 5 | = 6
| 11 - 10 | = 1
| 11 - 2 | = 9
max distance = 9
With element $arr1[3] = 3
| 3 - 2 | = 1
| 3 - 5 | = 2
| 3 - 10 | = 7
| 3 - 2 | = 1
max distance = 7
max (8, 9, 9, 7) = 9
Example 4:
Input: @arr1 = (1, 2, 3)
@arr2 = (3, 2, 1)
Output: 2
With element $arr1[0] = 1
| 1 - 3 | = 2
| 1 - 2 | = 1
| 1 - 1 | = 0
max distance = 2
With element $arr1[1] = 2
| 2 - 3 | = 1
| 2 - 2 | = 0
| 2 - 1 | = 1
max distance = 1
With element $arr1[2] = 3
| 3 - 3 | = 0
| 3 - 2 | = 1
| 3 - 1 | = 2
max distance = 2
max (2, 1, 2) = 2
Example 5:
Input: @arr1 = (1, 0, 2, 3)
@arr2 = (5, 0)
Output: 5
With element $arr1[0] = 1
| 1 - 5 | = 4
| 1 - 0 | = 1
max distance = 4
With element $arr1[1] = 0
| 0 - 5 | = 5
| 0 - 0 | = 0
max distance = 5
With element $arr1[2] = 2
| 2 - 5 | = 3
| 2 - 0 | = 2
max distance = 3
With element $arr1[3] = 3
| 3 - 5 | = 2
| 3 - 0 | = 3
max distance = 3
max (4, 5, 3, 3) = 5
There is no need for this ecessive checking. We can get away with computing these two differences only:
#! /usr/bin/env raku
unit sub MAIN ($arr1, $arr2); # [1]
my @arr1 = $arr1.words>>.Int; # [2]
my @arr2 = $arr2.words>>.Int; # [2a]
die "Non integer value(s) in arr1" unless all(@arr1) ~~ Int; # [3]
die "Non integer value(s) in arr2" unless all(@arr2) ~~ Int; # [3a]
say ((@arr1.max - @arr2.min).abs,
(@arr2.max - @arr1.min).abs).max; # [4]
[1] The two arrays as space separated strings.
[2] Use words
to split the values, and coerce the values to
Int
. Lazily.
[3] Ensure that we got integers only.
[4] See the section above. The abs
part is there
to get rid of a potential negative sign, as the difference is inherently positive.
E.g. 5 - 12 = -7
vs 12 - 5 = 7
.
See docs.raku.org/routine/abs for more information about abs
.
Running it:
$ ./max-distance "4 5 7" "9 1 3 4"
6
$ ./max-distance "2 3 4 5" "3 2 5 5 8 7"
6
$ ./max-distance "2 1 11 3" "2 5 10 2"
9
$ ./max-distance "1 2 3" "3 2 1"
2
$ ./max-distance "1 0 2 3" "5 0"
5
Looking good.
No verbose mode this time.
And that's it.