Perl Weekly Challenge 205: nested loops in a rush!
This post presents my solutions to the Perl Weekly Challenge 205.I keep doing the Perl Weekly Challenge in order to mantain my coding skills in good shape, as well as in order to learn new things, with particular regard to Raku, a language that I love.
This week, I solved the following tasks:
- PWC 205 - Task 1 - Raku
- PWC 205 - Task 2 - Raku
- PWC 205 - Task 1 in PostgreSQL PL/Perl
- PWC 205 - Task 2 in PostgreSQL PL/Perl
- PWC 205 - Task 1 in PostgreSQL PL/PgSQL
- PWC 205 - Task 2 in PostgreSQL PL/PgSQL
Raku Implementations
PWC 205 - Task 1 - Raku Implementation
The first task was about finding out the third max value within an array, if any, or the highest value. Simple enough, but selecting which value to extract from the sorted array required me to pass thru an intermediate list.sub MAIN( *@list where { @list.grep( * ~~ Int ).elems == @list.elems } ) {
my @highests = @list.unique.sort;
@highests[ * - ( @highests.elems > 2 ?? 3 !! 1 ) ].say;
}
The idea is to have
@list
sorted and filtered so that identical values are accounted only once. Then if the resulting @highests
array has more than three elements, I can grab the third maximum value, otherwise I grab the absolute max.
PWC 205 - Task 2 - Raku Implementation
Finding the highestxor
within an array. I used a double nested loop to find out the list of xor
-ed values, and then grab the maximum value.
sub MAIN( *@list where { @list.grep( * ~~ Int ).elems == @list.elems } ) {
my @xors;
for 0 ..^ @list.elems -> $left {
for $left ^..^ @list.elems -> $right {
@xors.push: @list[ $left ] +^ @list[ $right ];
}
}
@xors.max.say;
}
I spent a lot of time finding out why the
xor
operator (either xor
or ^^
) was not working, to find out that +^
was the right operator to use for integer xor.
PL/Perl Implementations
PWC 205 - Task 1 - PL/Perl Implementation
A little more verbose implementation than the Raku one.CREATE OR REPLACE FUNCTION
pwc205.task1_plperl( int[] )
RETURNS int
AS $CODE$
my ( $list ) = @_;
my $values = {};
$values->{ $_ }++ for ( sort $list->@* );
my $offset = keys( $values->%* ) > 2 ? -3 : -1;
return ( sort( keys( $values->%* ) ) )[ $offset ];
$CODE$
LANGUAGE plperl;
Since I don’t have a unique function at hand, I place the values into an hash using the values as keys, so that I eliminate duplicates. Then I compute an
$offset
to find out the max value to grab, and return it.
PWC 205 - Task 2 - PL/Perl Implementation
Similar to the Raku implementation, but I simply store the max value into a scalar$max
value.
CREATE OR REPLACE FUNCTION
pwc205.task2_plperl( int[] )
RETURNS int
AS $CODE$
my ( $list ) = @_;
my $max = 0;
for my $left ( 0 .. $list->@* ) {
for my $right ( $left + 1 .. $list->@* ) {
my $xor = $list->[ $left ] ^ $list->[ $right ];
$max = $xor if ( $xor > $max );
}
}
return $max;
$CODE$
LANGUAGE plperl;
PostgreSQL Implementations
PWC 205 - Task 1 - PL/PgSQL Implementation
Toward an SQL approach, I used a temporary table as a list of sorted elements. Then I count the number of tuples and decide how to limit the result set.CREATE OR REPLACE FUNCTION
pwc205.task1_plpgsql( l int[] )
RETURNS int
AS $CODE$
DECLARE
has_third_max int := 0;
third_max int := 0;
BEGIN
CREATE TEMPORARY TABLE IF NOT EXISTS t_sort( t int );
TRUNCATE t_sort;
INSERT INTO t_sort
SELECT t
FROM unnest( l ) t
GROUP BY t
HAVING count(*) = 1;
SELECT count(*)
INTO has_third_max
FROM t_sort;
IF has_third_max > 3 THEN
SELECT t
INTO third_max
FROM t_sort
ORDER BY t DESC
OFFSET 3
LIMIT 1;
ELSE
SELECT t
INTO third_max
FROM t_sort
ORDER BY t DESC
LIMIT 1;
END IF;
RETURN third_max;
END
$CODE$
LANGUAGE plpgsql;
PWC 205 - Task 2 - PL/PgSQL Implementation
Since doing thexor
in SQL is not as trivial as it could seem, I used a trick and invoked the PL/Perl implementation.
CREATE OR REPLACE FUNCTION
pwc205.task2_plpgsql( l int[] )
RETURNS int
AS $CODE$
SELECT pwc205.task2_plperl( l );
$CODE$
LANGUAGE sql;