This is my response to The Weekly Challenge #204.
Input: @nums = (1,2,2,3)
Output: 1
Example 2:
Input: @nums (1,3,2)
Output: 0
Example 3:
Input: @nums = (6,5,5,4)
Output: 1
This is easy, using the Reduction Metaoperator
[]
.
#! /usr/bin/env raku
unit sub MAIN (*@nums where @nums.elems >= 2 && all(@nums) ~~ /^<[0..9]>*$/);
# [1]
if [<=] @nums { say 1; } # [2]
elsif [>=] @nums { say 1; } # [3]
else { say 0; } # [4]
[1] Ensure at least two elements (as that should be the minimum for an array), and the values must be non-negative integers.
[2] The increasing rule: All the values (except the last one) must be
less than or equal (<=
) to the next one for this to be satisfied. The
Reduction Metaoperator []
applies the operator (the content of the brackets)
to the elements in the array. In this case [<=] (1, 2, 3)
is the same as
1 <= 2 <= 3
. The end result is a single Booolean value, thus the
Reduction part of the name.
See
docs.raku.org/language/operators#Reduction_metaoperators for more
information about the Reduction Metaoperator []
.
[3] The decreasing rule.
[4] Not Monotonic.
Running it:
$ ./monotonic-array 1 2 2 3
1
$ ./monotonic-array 1 3 2
0
$ ./monotonic-array 6 5 5 4
1
Looking good.
Verbose mode is missing in this program, as there really isn't anything to be verbose about.
Input: [ 1 2 ]
[ 3 4 ]
$matrix = [ [ 1, 2 ], [ 3, 4 ] ]
$r = 1
$c = 4
Output: [ 1 2 3 4 ]
Example 2:
Input: [ 1 2 3 ]
[ 4 5 6 ]
$matrix = [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]
$r = 3
$c = 2
Output: [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ]
[ 1 2 ]
[ 3 4 ]
[ 5 6 ]
Example 3:
Input: [ 1 2 ]
$matrix = [ [ 1, 2 ] ]
$r = 3
$c = 2
Output: 0
We need a way of specifying a matrix on the
command line, and the compact format I used in Ordered Search
for Raku (the program search-matrix2), my response to challenge 111, is equally suitable
here. Use spaces between the values, and |
between the rows. The three examples
can be specified by the following strings: "1 2 | 3 4"
,
"1 2 3 | 4 5 6"
and "1 2"
.
#! /usr/bin/env raku
unit sub MAIN (Str :m(:$matrix) = "1 2 | 3 4", # [1]
Int :$r where $r > 0 = 1, # [2]
Int :$c where $c > 0 = 4, # [2]
:v(:$verbose));
my @all = $matrix.split(/<[\s|]>+/); # [3]
my $count = @all.elems; # [4]
say ": All: { @all.raku }" if $verbose;
say ": Count: $count" if $verbose;
if $r * $c == $count # [5]
{
my @result; # [6]
for ^$r -> $row-id # [7]
{
my $start-index = $row-id * $c;
my $stop-index = $start-index + $c - 1;
say ": Row $row-id [ index $start-index .. $stop-index ]" if $verbose;
@result.push: @all[$start-index .. $stop-index]; # [8]
}
say @result.raku; # [9]
}
else # [10]
{
say 0; # [10]
}
[1] A named argument (the leading :
) for the matrix («--matrix»;
and the «-m» shortcut), as well as a default value.
[2] The r
and c
values, also as named arguments.
[3] We do not need the two dimentional matrix at all, so we unwrap the input
as a plain (one dimentional) array with this regex. If you do want the
two dimensions, this will do the trick:
$matrix.split("|")>>.words>>.List;
.
[4] The number of elements.
[5] We can only reshape the matrix if the number of values in both versions (input and output) are equal.
[6] The result (the rows in the new matrix) will end up here.
[7] Iterate over the row numbers (zero based) in the new matrix.
[8] Copy the relevant values, by their indices, and add them as a row to the new matrix.
[9] Print the result, using the builtin
raku
method.
See
docs.raku.org/routine/raku
for more information about the raku
method.
[10] Wrong number of elements (courtesy of [5]), if we get here. Print 0 (error).
Running it:
$ ./reshape-matrix -m="1 2 | 3 4" -r=1 -c=4
[("1", "2"),]
$ ./reshape-matrix -m="1 2 3| 4 5 6" -r=3 -c=2
[("1", "2"), ("3", "4"), ("5", "6")]
$ ./reshape-matrix -m="1 2" -r=3 -c=2
0
As expected.
With verbose mode:
$ ./reshape-matrix -v -m="1 2 | 3 4" -r=1 -c=4
: All: ["1", "2", "3", "4"]
: Count: 4
: Row 0 [ index 0 .. 3 ]
[("1", "2", "3", "4"),]
$ ./reshape-matrix -v -m="1 2 3|4 5 6" -r=3 -c=2
: All: ["1", "2", "3", "4", "5", "6"]
: Count: 6
: Row 0 [ index 0 .. 1 ]
: Row 1 [ index 2 .. 3 ]
: Row 2 [ index 4 .. 5 ]
[("1", "2"), ("3", "4"), ("5", "6")]
$ ./reshape-matrix -v -m="1 2" -r=3 -c=2
: All: ["1", "2"]
: Count: 2
0
We should probably get rid of the quotes, and use brackets (i.e. [
and ]
)
only:
#! /usr/bin/env raku
unit sub MAIN (Str :m(:$matrix) = "1 2 | 3 4",
Int :$r where $r > 0 = 1,
Int :$c where $c > 0 = 4,
:v(:$verbose));
my @all = $matrix.split(/<[\s|]>+/);
my $count = @all.elems;
say ": All: { @all.raku }" if $verbose;
say ": Count: $count" if $verbose;
if $r * $c == $count
{
my @result;
for ^$r -> $row-id
{
my $start-index = $row-id * $c;
my $stop-index = $start-index + $c - 1;
say ": Row $row-id [ index $start-index .. $stop-index ]" if $verbose;
@result.push: @all[$start-index .. $stop-index];
}
say @result.elems == 1
?? "[ { @result[0].join(", ") } ]" # [1]
!! "[ { @result.map({ '[' ~ @_.join(", ") ~ ']' }).join(", ") } ]"; # [2+]
}
else
{
say 0;
}
[1] Drop the outer brackets if there is only one row.
[2+] Two or more rows, with outer brackets.
Running it:
$ ./reshape-matrix2 -v -m="1 2 | 3 4" -r=1 -c=4
: All: ["1", "2", "3", "4"]
: Count: 4
: Row 0 [ index 0 .. 3 ]
[ 1, 2, 3, 4 ]
$ ./reshape-matrix2 -v -m="1 2 3|4 5 6" -r=3 -c=2
: All: ["1", "2", "3", "4", "5", "6"]
: Count: 6
: Row 0 [ index 0 .. 1 ]
: Row 1 [ index 2 .. 3 ]
: Row 2 [ index 4 .. 5 ]
[ [1 2], [3 4], [5 6] ]
$ ./reshape-matrix -v -m="1 2" -r=3 -c=2
: All: ["1", "2"]
: Count: 2
0
Looking good.
Some more, just for fun:
$ ./reshape-matrix2 -v -m="1 2 3|4 5 6" -r=2 -c=3
: All: ["1", "2", "3", "4", "5", "6"]
: Count: 6
: Row 0 [ index 0 .. 2 ]
: Row 1 [ index 3 .. 5 ]
[ [1 2 3], [4 5 6] ]
./reshape-matrix2 -v -m="1 2 3|4 5 6" -r=1 -c=6
: All: ["1", "2", "3", "4", "5", "6"]
: Count: 6
: Row 0 [ index 0 .. 5 ]
[ 1, 2, 3, 4, 5, 6 ]
$ ./reshape-matrix2 -v -m="1 2 3|4 5 6" -r=6 -c=1
: All: ["1", "2", "3", "4", "5", "6"]
: Count: 6
: Row 0 [ index 0 .. 0 ]
: Row 1 [ index 1 .. 1 ]
: Row 2 [ index 2 .. 2 ]
: Row 3 [ index 3 .. 3 ]
: Row 4 [ index 4 .. 4 ]
: Row 5 [ index 5 .. 5 ]
[ [1], [2], [3], [4], [5], [6] ]
And that's it.