by Arne Sommer

# Monotonically Reshaped Raku

 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]>*\$/); #  if [<=] @nums { say 1; } #  elsif [>=] @nums { say 1; } #  else { say 0; } #  ```

 Ensure at least two elements (as that should be the minimum for an array), and the values must be non-negative integers.

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

 The decreasing rule.

 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", #  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.raku; #  } else #  { say 0; #  } ```

 A named argument (the leading `:`) for the matrix («--matrix»; and the «-m» shortcut), as well as a default value.

 The `r` and `c` values, also as named arguments.

 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;`.

 The number of elements.

 We can only reshape the matrix if the number of values in both versions (input and output) are equal.

 The result (the rows in the new matrix) will end up here.

 Iterate over the row numbers (zero based) in the new matrix.

 Copy the relevant values, by their indices, and add them as a row to the new matrix.

 Print the result, using the builtin `raku` method.

See docs.raku.org/routine/raku for more information about the `raku` method.

 Wrong number of elements (courtesy of ), 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.join(", ") } ]" #  !! "[ { @result.map({ '[' ~ @_.join(", ") ~ ']' }).join(", ") } ]"; # [2+] } else { say 0; } ```

 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 ] [ , , , , ,  ] ```

And that's it.