# 解 Perl Weekly Challenge 084

Perl Weekly Challenge 084 本周兩題。一是將數字前後倒轉，二是在零壹矩陣中找出四角皆為一的正方形。

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

``````# Perl -- flip-integer.pl - v1
use v5.32;

sub flip_integer(\$n) {
my \$o = reverse(\$n);
}

my \$o = flip_integer(1234);

say \$o; #=> 4321``````

``````# Perl
use v5.32;

my @o = reverse(1234, 5678);
say join " ", @o;
#=> 5678 1234

my \$o = reverse(1234, 5678);
say \$o;
#=> 87654321``````

``````# Perl - flip-integer.pl - v2
use v5.32;

sub flip_integer {
my \$n = shift;
my \$o = reverse(\$n);
return \$o;
}

for my \$n (@ARGV) {
my \$o = flip_integer(\$n);
say "\$n -> \$o";
}``````

``````# perl flip-integer.pl 1234 00100 -678
1234 -> 4321
00100 -> 00100
-678 -> 876-``````

``````# Perl - flip-integer.pl - v3
use v5.32;

sub flip_integer {
my \$n = shift;
my \$sign = \$n < 0 ? -1 : 1;
my \$o = \$sign * reverse(abs(\$n));
return (-2**31 <= \$o < 2**31) ? \$o : 0;
}

for my \$n (@ARGV) {
my \$o = flip_integer(\$n);
say "\$n -> \$o";
}``````

Raku 版其實也差不多。不過在 Raku 中，將字串反轉的函式為 `flip`

``````# Raku
sub reverse-integer (Int \$n) {
my \$sign = \$n < 0 ?? -1 !! 1;
my \$o = \$sign * flip abs \$n;
return (-2³¹ ≤ \$o < 2³¹) ?? \$o !! 0;
}

for @*ARGS -> \$n {
say \$n ~ " -> " ~ reverse-integer(\$n.Int);
}``````

# TASK #2 › Find Square

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

``````use v5.32;
use List::Util qw(min);

sub find_squares {
my \$matrix = shift;

say "\n# Matrix";
for my \$row (@\$matrix) {
say join " ", @\$row;
}

say "#=> squares -> " . squares(\$matrix);
}

sub squares {
my (\$matrix, \$s) = @_;
my \$h = @\$matrix;
my \$w = @{\$matrix->[0]};

my \$c = 0;
for my \$s (2..min(\$w,\$h)) {
for my \$i (0..\$h-\$s) {
for my \$j (0..\$w-\$s) {
if (1 == \$matrix->[\$i][\$j] == \$matrix->[\$i+\$s-1][\$j] == \$matrix->[\$i][\$j+\$s-1] == \$matrix->[\$i+\$s-1][\$j+\$s-1]) {
\$c += 1;
}
}
}
}
return \$c;
}``````

``````sub find-squares(@matrix) {
say "\n# Matrix";
say .gist for @matrix;
say "#=> squares -> " ~ squares(@matrix);
}

sub squares(@matrix) {
return (2 .. min(@matrix.elems, @matrix[0].elems)).map(
-> \$s {
((0..@matrix.elems-\$s) X (0..@matrix[0].elems-\$s)).grep(
-> @c {
1 == [[0,0], [\$s-1,0], [0,\$s-1], [\$s-1, \$s-1]]
.map({ \$_ <<+>> @c })
.map({ @matrix[ \$_[0] ][ \$_[1] ] })
.all
}
).elems
}).sum;
}``````

`X` 這個能得出兩集合外積的算符實在很簡便。只要一小段算式就能取代兩個巢狀迴圈。