# Perl Weekly Challenge 225: I’m back

This post presents my solutions to the Perl Weekly Challenge 225.
I know I’ve been not solving tasks for a while, a month or so, but the fact is that I recently changed my main job and therefore I was very busy in finishing up all the things at my previous job, as well as learning everything from scratch where I’m now!
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 225 - Task 1 - Raku Implementation

Given a list of sentences, where each word is separated by a single space, output the max counting of words in a sentence.

``````sub MAIN( *@sentences ) {
my %data;
%data{ \$_ } = \$_.split( /\s/ ).elems for @sentences;
%data.values.max.say;
}

``````

I soved with a simple hash that is keyed by the sentence and keep track of the word counting, then I select the max value.

## PWC 225 - Task 2 - Raku Implementation

Given a list of integers, produce a left-right sum, which is kind of bizzarre.

``````sub MAIN( *@numbers where { @numbers.grep( * ~~ Int ).elems == @numbers.elems } ) {
my ( @left, @right );

@left.push: 0;
@left.push: @numbers[ 0 .. \$_ ].sum for 0 ..^ @numbers.elems - 1;

@right.push: @numbers[ \$_ .. * ].sum for 1 ..^ @numbers.elems;
@right.push: 0;

say @left;
say @right;

(@left Z[-] @right).map( { \$_.abs } ).say;
}

``````

I use the `Z[-]` operator to mix the arrays producing the difference, then I `map` the result into a only positive value.

# PL/Perl Implementations

## PWC 225 - Task 1 - PL/Perl Implementation

As usual, more verbose than its counterpart in Raku, but still a simple task. I keep track of the max value as long as I iterate across all the sentences:

``````CREATE OR REPLACE FUNCTION
RETURNS int
AS \$CODE\$
my ( \$sentences ) = @_;

my \$max = 0;

for ( \$sentences->@* ) {
my \$count = scalar split( /\s/, \$_ );
\$max = \$max > \$count ? \$max : \$count;
}

return \$max;
\$CODE\$
LANGUAGE plperl;

``````

The trick here is to count, by means of `scalar`, the words in a `split`ted sentence.

## PWC 225 - Task 2 - PL/Perl Implementation

A translation of the Raku implementation, but with a single final loop to zip the arrays:

``````CREATE OR REPLACE FUNCTION
RETURNS SETOF int
AS \$CODE\$
my ( \$numbers ) = @_;

my ( @left, @right );

push @left, 0;
for my \$index ( 0 .. scalar( \$numbers->@* ) - 2 ) {
my \$sum = 0;
\$sum += \$_ for ( \$numbers->@[ 0 .. \$index ] );
push @left, \$sum;
}

for my \$index ( 1 .. scalar( \$numbers->@* ) - 1 ) {
my \$sum = 0;
\$sum += \$_ for ( \$numbers->@[ \$index .. scalar( \$numbers->@* )  ] );
push @right, \$sum;
}

for my \$index ( 0 .. \$#left ) {
my \$value = \$left[ \$index ] - \$right[ \$index ];
\$value = \$value > 0 ? \$value : \$value * - 1;
return_next( \$value );
}

return undef;

\$CODE\$
LANGUAGE plperl;

``````

Note that since I iterate on `@left` I don’t need the final zero in the `@right` array.

# PostgreSQL Implementations

## PWC 225 - Task 1 - PL/PgSQL Implementation

Similar to the PL/Perl implementation, but I use the SQL to count the words since I can split a text into a table:

``````CREATE OR REPLACE FUNCTION
pwc225.task1_plpgsql( sentences text[] )
RETURNS int
AS \$CODE\$
DECLARE
current_sentence text;
max_length int := 0;
current_length int := 0;
BEGIN
FOREACH current_sentence IN ARRAY sentences LOOP
SELECT count(*)
INTO current_length
FROM regexp_split_to_table( current_sentence, ' ' );

IF current_length > max_length THEN
max_length := current_length;
END IF;
END LOOP;

RETURN max_length;
END
\$CODE\$
LANGUAGE plpgsql;

``````

## PWC 225 - Task 2 - PL/PgSQL Implementation

Similar to the PL/Perl implementation, makes usage of arrays and internal state.

``````CREATE OR REPLACE FUNCTION
pwc225.task2_plpgsql( numbers int[] )
RETURNS SETOF INT
AS \$CODE\$
DECLARE
current_value int := 0;
current_sum int := 0;

current_index int := 0;
current_sub_index int := 0;
a_left int[];
a_right int[];
BEGIN

a_left := array_append( a_left, 0 );
current_index := 0;
FOR current_index IN 1 .. array_length( numbers, 1 ) - 1 LOOP
current_sum := 0;
FOR current_sub_index IN 1 .. current_index LOOP
current_sum := current_sum + numbers[ current_sub_index ];
END LOOP;
a_left := array_append( a_left, current_sum );
END LOOP;

current_index := 0;
FOR current_index IN 2 .. array_length( numbers, 1 )  LOOP
current_sum := 0;
FOR current_sub_index IN current_index .. array_length( numbers, 1 ) LOOP
current_sum := current_sum + numbers[ current_sub_index ];
END LOOP;
a_right := array_append( a_right, current_sum );
END LOOP;

a_right := array_append( a_right, 0 );

FOR current_index IN 1 .. array_length( a_left, 1 ) LOOP
current_value := a_left[ current_index ] - a_right[ current_index ];
IF current_value > 0 THEN
RETURN NEXT current_value;
ELSE
RETURN NEXT ( current_value * -1 );
END IF;
END LOOP;

RETURN;

END
\$CODE\$
LANGUAGE plpgsql;

``````

The article Perl Weekly Challenge 225: I'm back has been posted by Luca Ferrari on July 12, 2023