Perl Weekly Challenge 244: grep and filter everywhere!

This post presents my solutions to the Perl Weekly Challenge 244.
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:
The PL/Perl implementations are very similar to a pure Perl implementation, even if the PostgreSQL environment could involve some more constraints. Similarly, the PL/PgSQL implementations help me keeping my PostgreSQL programming skills in good shape.

Raku Implementations

PWC 244 - Task 1 - Raku Implementation

The first task was about producing an array of integers where each element is the counting of how many integers are greater than the given input valu within an array of integers.

sub MAIN( *@nums where { @nums.elems == @nums.grep( * ~~ Int ).elems } ) {
    my @result;
    @result[ $_ ] = @nums.grep( * > @nums[ $_ ] ).elems  for 0 ..^ @nums.elems;
    @result.say;
}



PWC 244 - Task 2 - Raku Implementation

The second task was about computing the power of a group of heroes, each one with a given strenght in an array of integers. There was the need to comput all the possible combinations of heroes.

sub MAIN( *@nums where { @nums.elems == @nums.grep( * ~~ Int ).elems } ) {

    my $power = 0;
    for @nums.combinations {
		next if ! $_;
		$power +=  $_.min * ( $_.max  ** 2 );
    }

    $power.say;
}



PL/Perl Implementations

PWC 244 - Task 1 - PL/Perl Implementation

Similar to the Raku implementation.

CREATE OR REPLACE FUNCTION
pwc244.task1_plperl( int[] )
RETURNS SETOF int
AS $CODE$
   my ( $nums ) = @_;

   for my $needle ( $nums->@* ) {
       return_next( scalar( grep( { $_ > $needle } $nums->@* ) ) );
   }

   return undef;
$CODE$
LANGUAGE plperl;



PWC 244 - Task 2 - PL/Perl Implementation

I decide to use two libraries, List::Util and Alghoritm::Combinatorics to get functions that can help me get all the combinations and the needed min and max values out of an array.

CREATE OR REPLACE FUNCTION
pwc244.task2_plperl( int[] )
RETURNS int
AS $CODE$
   use Algorithm::Combinatorics qw/ combinations /;
   use List::Util qw/ min max /;

   my ( $nums ) = @_;
   my $power;

   $power = 0;

   for my $k ( 1 .. $nums->@* ) {
       my $combinations = combinations( \ $nums->@*, $k );
       while ( my $iter = $combinations->next ) {
       	     $power += min( $iter->@* ) * ( max( $iter->@* ) ** 2 );
       }
   }


   return $power;
$CODE$
LANGUAGE plperlu;



There is an interesting thing to note here: even if $nums is like an array reference, the combinations method does not accept it as an arrayref, and therefore I needed to transform it into an array and get back the explicit reference.

PostgreSQL Implementations

PWC 244 - Task 1 - PL/PgSQL Implementation

It is easy enough to get the count of the elements greater than the given one, thanks to a single query.

CREATE OR REPLACE FUNCTION
pwc244.task1_plpgsql( nums int[] )
RETURNS SETOF int
AS $CODE$
DECLARE
	v int;
	returning int;
BEGIN
	FOREACH v IN ARRAY nums LOOP
		SELECT count(*)
		INTO returning
		FROM unnest( nums ) n
		WHERE n > v;

		RETURN NEXT returning;
	END LOOP;

	RETURN;
END
$CODE$
LANGUAGE plpgsql;



PWC 244 - Task 2 - PL/PgSQL Implementation

I cheated here! Since obtaining all the combinations is too much work to be done in SQL, I delegated the PL/Perl to answer the task.

CREATE OR REPLACE FUNCTION
pwc244.task2_plpgsql( nums int[] )
RETURNS int
AS $CODE$
   SELECT pwc244.task2_plperl( nums );
$CODE$
LANGUAGE sql;



Python Implementations

PWC 244 - Task 1 - Python Implementation

I use filter as an alternative to the Perl’s grep function, then I append the single result into the result array and output it.

import sys

# task implementation
def main( argv ):
    nums = list( map( int, argv ) )
    result = []

    for current in nums:
        result.append( len( list( filter( lambda x: x > current, nums ) ) ) )

    print( ", ".join( map( str, result ) ) )


# invoke the main without the command itself
if __name__ == '__main__':
    main( sys.argv[ 1: ] )




PWC 244 - Task 2 - Python Implementation

I use itertoolsd.combinations to get all the possible combinations, even if I need one unit more than the len of the array.

import sys
from itertools import combinations;

# task implementation
def main( argv ):
    nums = list( map( int, argv ) )
    power = 0

    for size in range( 1, len( nums ) + 1 ):
        for current in combinations( nums, size ):
            power = power + ( max( current ) ** 2 ) * min( current )

    print( power )



# invoke the main without the command itself
if __name__ == '__main__':
    main( sys.argv[ 1: ] )



The article Perl Weekly Challenge 244: grep and filter everywhere! has been posted by Luca Ferrari on November 20, 2023