I’ve been doing the Perl Weekly
Challenges. The
latest
involved reversing integers and a two-dimensional search. (Note that
this is open until 1 November 2020.)
Task #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 first part is easy, of course. The second is rather harder: all
four of the languages I'm using have larger standard integer types
than 32 bits.
So in Perl we have:
my $r=join('',reverse split '',$s);
if ($r =~ /([0-9]+)-$/) {
$r="-$1";
}
Raku, with more complicated regexp syntax:
my $r=$s.comb.reverse.join('');
if ($r ~~ /(<[0..9]>+)\-$/) {
$r="-$0";
}
Python:
a=str(s)[::-1]
if (a[-1] == '-'):
a='-' + a[0:-1]
Ruby:
a=str(s)[::-1]
if (a[-1] == '-'):
a='-' + a[0:-1]
But how do we test whether the thing will fit into 32-bit signed?
Well, these languages may not have 32-bit data types, but they can
encode/decode them for use with packed formats. So in Perl:
if (unpack('l',pack('l',$r)) != $r) {
return 0;
}
return $r;
Python (needs a cast to integer):
a=int(a)
try:
b=struct.pack('<l',a)
except struct.error as err:
return 0
return a
Ruby (ditto):
r=Integer(r)
b=[r].pack('l').unpack('l')[0]
if b != r
return 0
end
return r
But what about Raku? Well, its pack
is still very primitive. But
unlike the other languages here it does have an explicitly
32-bit-wide integer type. So I cast to that (which, perversely,
doesn't raise an error if it doesn't fit) and see if it worked.
my int32 $b=Int($r);
if ($b != $r) {
return 0;
}
return $r;
Task #2 › Find Square
You are given matrix of size m × n
with only 1
and 0
.
Write a script to find the count of squares having all four corners
set as 1
.
So it's basically a two-dimensional search, but the delta-x and
delta-y terms are always the same. Pretty straightforward really
(using Perl for the example): find the array size;
my $t=0;
my $maxx=$#{$s};
my $maxy=$#{$s->[0]};
iterate over each possible starting point;
foreach my $x (0..$maxx-1) {
foreach my $y (0..$maxy-1) {
see if that point is a potential anchor;
if ($s->[$x][$y]==1) {
if so, iterate over all the sizes of square that might fit;
foreach my $d (1..min($maxx-$x,$maxy-$y)) {
and check the other three corners.
if ($s->[$x+$d][$y]==1 &&
$s->[$x][$y+$d]==1 &&
$s->[$x+$d][$y+$d]==1
) {
$t++;
And the other languages basically work the same way. Python wants a
range
operator, but otherwise they're all identical apart from minor
details of syntax.
One could I suppose build a table of potential opposite corners but
I'm not convinced that there's much optimisation to be had.
Full code on github.
Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.