Perl Weekly Challenge 321: Task 2 simpler than Task 1

This post presents my solutions to the Perl Weekly Challenge 321.
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 321 - Task 1 - Raku Implementation

In the first task, given an array of integers, the script has to provide the min intermediate average, as computed from progressively average the min and max value left in the array.

sub MAIN( *@numbers where { @numbers.elems %% 2 && @numbers.elems == @numbers.grep( * ~~ Int ).elems } ) {

    my @averages;
    for 0 ..^ @numbers.elems / 2 {
		@averages.push: ( [+] @numbers.sort[ $_, * - 1 - $_ ] ) / 2;
    }

    @averages.min.say;
}



The idea is quite simple: I iterate over the boundaries of the array, compute the average and store it into the @averages array. Then, print the min value.

PWC 321 - Task 2 - Raku Implementation

Given two strings, assume the # is a backspace and hence deletes the left character. Return True if the strings are the same.

sub MAIN( Str $left, Str $right ) {
    say $left.subst( / . <[#]> /, '', :g ) ~~ $right.subst( / . <[#]> /, '', :g );
}



A single line does suffice: if the strings, after having substituted the backspace chaacters, do match then return True.

PL/Perl Implementations

PWC 321 - Task 1 - PL/Perl Implementation

Similar implemenration to the Raku one.

CREATE OR REPLACE FUNCTION
pwc321.task1_plperl( int[] )
RETURNS numeric
AS $CODE$

   my ( $numbers ) = @_;
   die "Must be even in size!" if ( $numbers->@* % 2 != 0 );

   $numbers = [ sort $numbers->@* ];

   my $min_average = undef;

   for ( 0 .. $numbers->@* - 1 ) {
       my $current = ( $numbers->@[ $_ ] + $numbers->@[ $numbers->@* - $_ - 1 ] ) / 2;
       $min_average = $current if ( ! $min_average || $min_average > $current );
   }

   return $min_average;

$CODE$
LANGUAGE plperl;



This time, instead of having an array of averages, I keep directly the min value computed at each iteration.

PWC 321 - Task 2 - PL/Perl Implementation

Similar implementation to the Raku one.

CREATE OR REPLACE FUNCTION
pwc321.task2_plperl( text, text )
RETURNS boolean
AS $CODE$

   my ( $left, $right ) = @_;

   $left  =~ s/ . [#]//xg;
   $right =~ s/ . [#]//xg;

   return $left eq $right ? 1 : 0;

$CODE$
LANGUAGE plperl;



PostgreSQL Implementations

PWC 321 - Task 1 - PL/PgSQL Implementation

In this implementation I use a temporary table to store the computed averages, so that I can extract the min value from such table.

CREATE OR REPLACE FUNCTION
pwc321.task1_plpgsql( numbers int[] )
RETURNS numeric
AS $CODE$
DECLARE
	i int;
	result numeric;
	current int[];
BEGIN
	CREATE TEMPORARY TABLE IF NOT EXISTS averages( v numeric, mx int, mn int );
	TRUNCATE averages;

	FOR i IN 0 .. array_length( numbers, 1 ) / 2 - 1 LOOP

	    INSERT INTO averages( v, mx, mn )
	    SELECT ( min( x::int ) + max( x::int ) ) / 2::numeric
	    	   , max( x )::int
	    	   , min( x )::int

	    FROM unnest( numbers[ 1 + i : array_length( numbers, 1 ) - i ] ) x
	    ;
	END LOOP;

	SELECT min( v )
	INTO result
	FROM averages;

	RETURN result;
END
$CODE$
LANGUAGE plpgsql;



Note that the unnest works on array slice, not two single elements, but since I then apply min and max, I get the same result as having computed only two values.

PWC 321 - Task 2 - PL/PgSQL Implementation

Use regexp_replace to do the trick, so that a single query does suffice.

CREATE OR REPLACE FUNCTION
pwc321.task2_plpgsql( l text, r text )
RETURNS boolean
AS $CODE$
   SELECT regexp_replace( l, '.[#]', '', 'g' ) = regexp_replace( r, '.[#]', '', 'g' );
$CODE$
LANGUAGE sql;



Java Implementations

PWC 321 - Task 1 - PostgreSQL PL/Java Implementation

Iterative approach in Java, using a collection and keeping the min value computed at every iteration.

    @Function( schema = "pwc321",
	       onNullInput = RETURNS_NULL,
	       effects = IMMUTABLE )
    public static final Float task1_pljava( int[] numbers ) throws SQLException {
		logger.log( Level.INFO, "Entering pwc321.task1_pljava" );

		if ( numbers.length % 2 != 0 )
		    throw new SQLException( "Must be even in size" );

		Float min_average = null;

		List<Integer> sorted = IntStream.of( numbers ).boxed().collect( Collectors.toList() );
		Collections.sort( sorted );

		for ( int i = 0; i < sorted.size(); i++ ) {
		    float current = ( sorted.get( i ) + sorted.get( sorted.size() - i - 1 ) ) / (float) 2;
		    if ( min_average == null || current < min_average )
				min_average = current;
		}

		return min_average;
    }
}



PWC 321 - Task 2 - PostgreSQL PL/Java Implementation

Using regular expression to the rescue.

	@Function( schema = "pwc321",
	       onNullInput = RETURNS_NULL,
	       effects = IMMUTABLE )
    public static final boolean task2_pljava( String left, String right ) throws SQLException {
		logger.log( Level.INFO, "Entering pwc321.task2_pljava" );

	    return left.replaceAll( ".[#]", "" ).equals( right.replaceAll( ".[#]", "" ) );
    }


Python Implementations

PWC 321 - Task 1 - Python Implementation

Same implementation as in PL/Perl.

import sys

# task implementation
# the return value will be printed
def task_1( args ):
    numbers = list( sorted( list( map( int, args ) ) ) )
    min_average = None

    for i in range( 0, len( numbers ) ):
        current = ( numbers[ i ] + numbers[ len( numbers ) - i - 1 ] ) / 2
        if min_average is None or current < min_average:
            min_average = current

    return min_average


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



PWC 321 - Task 2 - Python Implementation

Use regular expressions to compare the strings.

import sys
import re

# task implementation
# the return value will be printed
def task_2( args ):
    left  = args[ 0 ]
    right = args[ 1 ]

    left  = re.sub( '.[#]', '', left )
    right = re.sub( '.[#]', '', right )

    return left == right


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



The article Perl Weekly Challenge 321: Task 2 simpler than Task 1 has been posted by Luca Ferrari on May 12, 2025