by Arne Sommer

# Monotonically Reshaped Raku

[224] Published 14. February 2023.

This is my response to The Weekly Challenge #204.

## Challenge #204.1: Monotonic Array

You are given an array of integers.

Write a script to find out if the given array is Monotonic. Print 1 if it is otherwise 0.

An array is Monotonic if it is either monotone increasing or decreasing.

Example 1: ```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 `[]`.

File: monotonic-array ```#! /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.

## Challenge #204.2: Reshape Matrix

You are given a matrix (m x n) and two integers (r) and (c).

Write a script to reshape the given matrix in form (r x c) with the original value in the given matrix. If you can’t reshape print 0.

Example 1: ```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"`.

File: reshape-matrix ```#! /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:

File: reshape-matrix2 ```#! /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.