### Perl Weekly Challenge: Week 84

#### Challenge 1:

Reverse Integer

You are given an integer `\$N`.

Write a script to reverse the given integer and print the result. Print 0 if the result doesnâ€™t fit in 32-bit signed integer.

The number `2,147,483,647` is the maximum positive value for a 32-bit signed binary integer in computing.

##### Example 1:
``````Input: 1234
Output: 4321
``````
##### Example 2:
``````Input: -1234
Output: -4321
``````
##### Example 3:
``````Input: 1231230512
Output: 0
``````

This is the code I wrote for Perl based on a C function I had written some time ago. In hindsight this could be a lot more perlish.

``````my \$num = shift;
my \$sign = 0;

if (\$num < 0) {
\$sign = 1;
\$num = abs(\$num);
}

if (\$num > 2_147_483_647) {
say '0';
} else {
``````

For instance I could have replaced the entire `while` loop by treating `\$num` as a string and reversing it with the `reverse()` function.

``````    my \$reversed = 0;

while (\$num > 0) {
\$reversed = \$reversed * 10 + \$num % 10;
\$num = int (\$num / 10);
}

say \$sign ? q{-} : q{}, \$reversed;
}
``````

(Full code on Github.)

The same criticism applies to the Raku version but, oh well, atleast it works.

``````sub MAIN(Int \$n) {
``````

Because function parameters are immutable, `\$n` needs to be copied to another variable if we want to slice and dice it.

``````    my \$num = \$n;
``````

I could have used `True` and `False` for `\$sign` as Raku has a boolean type.

``````    my \$sign = 0;

if (\$num < 0) {
\$sign = 1;
\$num = abs(\$num);
}

if \$num > 2_147_483_647 {
say '0';
} else {
my \$reversed = 0;

while \$num > 0 {
\$reversed = \$reversed * 10 + \$num % 10;
``````

In Perl I had to use the `int()` function to make sure the result of the division was an integer. Raku has an integer division operator, `div` so it's not necessary here.

``````            \$num div= 10;
}

say \$sign ?? q{-} !! q{}, \$reversed;
}
}
``````

(Full code on Github.)

#### Challenge 2:

Flip Array

You are given matrix of size `m x n` with only `1` and `0`.

Write a script to find the count of squares having all four corners set as `1`.

##### Example 1:
``````Input: [ 0 1 0 1 ]
[ 0 0 1 0 ]
[ 1 1 0 1 ]
[ 1 0 0 1 ]

Output: 1
``````
###### EXPLANATION

There is one square (3x3) in the given matrix with four corners as 1 starts at r=1;c=2.

``````[ 1 0 1 ]
[ 0 1 0 ]
[ 1 0 1 ]
``````
##### Example 2:
``````Input: [ 1 1 0 1 ]
[ 1 1 0 0 ]
[ 0 1 1 1 ]
[ 1 0 1 1 ]

Output: 4
``````
###### EXPLANATION

There is one square (4x4) in the given matrix with four corners as 1 starts at r=1;c=1.

There is one square (3x3) in the given matrix with four corners as 1 starts at r=1;c=2.

There are two squares (2x2) in the given matrix with four corners as 1. First starts at r=1;c=1 and second starts at r=3;c=3.

##### Example 3:
``````Input: [ 0 1 0 1 ]
[ 1 0 1 0 ]
[ 0 1 0 0 ]
[ 1 0 0 1 ]

Output: 0
``````

I'll show you the Raku solution first.

``````sub MAIN(
Str \$file #= a file describing a matrix of 1's and 0's where every line
#= is a row in the matrix.
) {
my @matrix;
``````

As entering a matrix on the command line would have been a bit awkward, I elected to read in text files where each row of 1's and 0's would be a separate line. This code reads such a file in and populates a 2d array, `@matrix` with the separated digits. If this code were being used in a production script, I would do a lot of checking to make sure it is in the correct format. As it stands, it just trusts the input will be usable.

``````    for \$file.IO.lines -> \$line {
@matrix.push(\$line.comb);
}

my \$squares = 0;
``````

A double `for` loop sets up each row of the matrix as `\$m` and each column as `\$n`.

As we traverse the matrix, each element is checked if it is a 1. If it is, another loop is started, this time a C-style `for` loop; Raku reserves the `for` keyword for iteration over ranges and uses `loop` for the C-style one. This loop increments `\$side` until we get to another `1` or we hit the right hand edge of the matrix.

If we did find a second `1`, we have the top two corners of a square. We now go down `\$side` rows (once again bounds checking) and then accross `\$side` columns and see if there are `1`'s in those two locations. If there are, we have a square.

In production code I would consider 5 nested blocks as a code smell and try and refactor this into several functions.

``````    for 0 ..^ @matrix.elems -> \$m {
for 0 ..^ @matrix[\$m].elems -> \$n {
if @matrix[\$m][\$n] == 1 {
loop (my \$side = 1; \$n + \$side < @matrix[\$m].elems; \$side++) {
if @matrix[\$m][\$n + \$side] == 1
&& \$m + \$side < @matrix.elems
&& @matrix[\$m + \$side][\$n] == 1
&& @matrix[\$m + \$side][\$n + \$side] == 1 {
\$squares++;
}
}
}
}
}

say \$squares;
}
``````

(Full code on Github.)

And this is Perl. The chief thing to note here is that Perl doesn't have real multidimensional arrays so our matrix is an array of array references which makes accessing elements a bit awkward.

``````my \$file = shift // usage();

my @matrix;
open my \$fn, '<', \$file or die "\$OS_ERROR\n";
while (my \$line = <\$fn>) {
chomp \$line;
push @matrix, [ split //, \$line ];
}
close \$fn;

my \$squares = 0;

for my \$m (0 .. scalar @matrix - 1) {
for my \$n (0 .. (scalar @{\$matrix[\$m]} - 1)) {
if (\$matrix[\$m]->[\$n] == 1) {
for (my \$side = 1; \$n + \$side < scalar @{\$matrix[\$m]}; \$side++) {
if (\$matrix[\$m]->[\$n + \$side] == 1
&& \$m + \$side < scalar @matrix
&& \$matrix[\$m + \$side]->[\$n] == 1
&& \$matrix[\$m + \$side]->[\$n + \$side] == 1) {
\$squares++;
}
}
}
}
}

say \$squares;
``````

(Full code on Github.)