Perl Weekly Challenge 201: not satisfied!
This post presents my solutions to the Perl Weekly Challenge 201.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 201 - Task 1 - Raku
- PWC 201 - Task 2 - Raku
- PWC 201 - Task 1 in PostgreSQL PL/Perl
- PWC 201 - Task 2 in PostgreSQL PL/Perl
- PWC 201 - Task 1 in PostgreSQL PL/PgSQL
- PWC 201 - Task 2 in PostgreSQL PL/PgSQL
Raku Implementations
PWC 201 - Task 1 - Raku Implementation
The first task was about searching for missing numbers in a given list of scattered (i.e., unordered) numbers. This is a matter ofgrep
ping every number in a range:
sub MAIN( *@n where { @n.grep( * ~~ Int ) == @n.elems } ) {
my @missing-numbers;
for 0 ^.. @n.elems {
@missing-numbers.push: $_ if ( ! @n.grep( $_ ) );
}
@missing-numbers.join( ', ' ).say;
}
PWC 201 - Task 2 - Raku Implementation
The second task is much more complex than the first one, and it involves computing the integer partitions for a given input number. It turned out that this task is too much difficult for me to solve, and that’s why I’m not satisfied in using an external library to achieve the result. However, thanks toMath::Combinatorics
, I can use the partitions
method that gives me the result:
use Math::Combinatorics <partitions>;
sub MAIN( Int $n where { $n > 0 } ) {
say partitions( $n ).elems;
}
PL/Perl Implementations
A very similar implementation to the Raku one, so I dogrep
for a given number in the input list:
PWC 201 - Task 1 - PL/Perl Implementation
CREATE OR REPLACE FUNCTION
pwc201.task1_plperl( int[] )
RETURNS SETOF int
AS $CODE$
my ( $n ) = @_;
for my $needle ( 1 .. $n->@* ) {
return_next( $needle ) if ( ! grep( { $_ == $needle } $n->@* ) );
}
return;
$CODE$
LANGUAGE plperl;
PWC 201 - Task 2 - PL/Perl Implementation
Again, I had to involve an external library, this timeIntegher::Partitions
.
CREATE OR REPLACE FUNCTION
pwc201.task2_plperl( int)
RETURNS int
AS $CODE$
use Integer::Partition;
my $partitions = Integer::Partition->new( $_[0] );
my $count = 0;
$count++ while( $partitions->next );
return $count;
$CODE$
LANGUAGE plperlu;
This means that the code has to be written as
plperlu
, i.e., it is untrusted. Moreover, the Integer::Partiton
library does provide only an iterative interface, so I need to manually count all the partitions before returning the result.
PostgreSQL Implementations
PWC 201 - Task 1 - PL/PgSQL Implementation
The first task can be solved with a simple SQL query:CREATE OR REPLACE FUNCTION
pwc201.task1_plpgsql( n int[] )
RETURNS SETOF int
AS $CODE$
SELECT v
FROM generate_series( 1, array_length( n, 1 ) ) v
WHERE v NOT IN
( SELECT unnest( n ) );
$CODE$
LANGUAGE sql;
The function accepts an array and transforms it into a table by means of the
unnest
function. The result is then joined with the result of generate_series
, a function that produces a sequences of integers. I keep only the tuples that do not match, meaning I’m keeping all the numbers that are not in the original array.
PWC 201 - Task 2 - PL/PgSQL Implementation
Again, I’m not satisfied of this solution! Since it is not simple to achieve this in SQL, I decided to simply call the PL/Perl implementation, that in turns calls an external module function, and this means there is nothing out of my bag here!CREATE OR REPLACE FUNCTION
pwc201.task2_plpgsql( n int )
RETURNS int
AS $CODE$
SELECT pwc201.task2_plperl( n );
$CODE$
LANGUAGE sql;