Perl Weekly Challenge 352: and here comes Christmas

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

The task was about to find out if a word is contained in any subsequent words in a given list.

sub MAIN( *@strings ) {
    my %found;
    for 0 ..^ @strings.elems {
		my $current = @strings[ $_ ];
		%found{ $current } = @strings[ $_ + 1 .. * - 1 ].grep( * ~~ / $current / ).elems;
    }

    %found.kv.grep( -> $k, $v { $v > 0 } ).map( *[0] ).join( ', ' ).say;
}



This is an accurate implementation, since it uses a %found hash to count how many times the same word appears in the subsequent words. The last line exploits the list of couples keys, values and searches for a value greater than zero, that is the word appears at least another time. The resulting list is then mapped to the key only, i.e., the word, and then the list is joined and printed out.

PWC 352 - Task 2 - Raku Implementation

Given a list of bits, compose numbers from left to right one digit at a time, and see which are divisible by 5.

sub MAIN( *@bits where { @bits.grep( * ~~ / <[0|1]> / ).elems == @bits.elems } ) {
    my @binaries;
    for 0 ..^ @bits.elems {
		my $val = @bits[ 0 .. $_ ].join.parse-base( 2 ).Int;
		@binaries.push: @bits[ 0 .. $_ ].join if ( $val %% 5 );
    }

    @binaries.join( ', ' ).say;
}



Simple enough, the $val is the joined bits from left to right, parsed in base 2 and converted to an integer. If such value is divisible %% by 5 the value is pushed to @binaries, that is last printed out.

PL/Perl Implementations

PWC 352 - Task 1 - PL/Perl Implementation

In this implementation, I output one at a time, the matching words by means of using a regular expression.

CREATE OR REPLACE FUNCTION
pwc352.task1_plperl( text[] )
RETURNS SETOF text
AS $CODE$

   my ( $strings ) = @_;

   for my $i ( 0 .. scalar $strings->@* ) {
     my $current = $strings->[ $i ];

     for my $j ( $i + 1 .. scalar $strings->@* ) {
     	 return_next( $current ) if ( $strings->[ $j ] =~ / $current /x );
     }
   }

   return undef;
$CODE$
LANGUAGE plperl;



PWC 352 - Task 2 - PL/Perl Implementation

The implementation is pretty much the same as in Raku, using oct to convert the string of the binary bits into an integer.

CREATE OR REPLACE FUNCTION
pwc352.task2_plperl( int[] )
RETURNS SETOF text
AS $CODE$

   my ( $bits ) = @_;

   my @binaries;
   for ( 0 .. $bits->@* - 1 ) {
       push @binaries, join( '', $bits->@[ 0 .. $_ ] );
   }

   for my $val ( @binaries ) {
       if ( oct( "0b". $val ) % 5 == 0 ) {
       	  return_next( $val );
       }
   }

   return undef;
$CODE$
LANGUAGE plperl;



PostgreSQL Implementations

PWC 352 - Task 1 - PL/PgSQL Implementation

Same implementation as in PL/Perl.

CREATE OR REPLACE FUNCTION
pwc352.task1_plpgsql( strings text[] )
RETURNS SETOF text
AS $CODE$
DECLARE
	counter int;
BEGIN
	counter := 0;

	FOR i IN 1 .. array_length( strings, 1 ) LOOP
	    SELECT count( v )
	    INTO   counter
	    FROM   unnest( strings[ i + 1 : array_length( strings, 1 ) ] ) v
	    WHERE  v like '%' || strings[ i ] || '%'
	    ;


	    IF counter > 0 THEN
	       RETURN NEXT strings[ i ];
	    END IF;

	END LOOP;

	RETURN;
END
$CODE$
LANGUAGE plpgsql;



PWC 352 - Task 2 - PL/PgSQL Implementation

Same implementation as in PL/Perl.

CREATE OR REPLACE FUNCTION
pwc352.task2_plpgsql( bits bit[] )
RETURNS SETOF text
AS $CODE$
DECLARE
	c int;
BEGIN

	FOR i IN 1 .. array_length( bits, 1 ) LOOP
	    c := cast( '0b' || array_to_string( bits[ 1 : i ], '' ) as int );
	    IF mod( c, 5 ) = 0 THEN
	       RETURN NEXT array_to_string( bits[ 1 : i ], '' );
	    END IF;
	END LOOP;

	RETURN;
END
$CODE$
LANGUAGE plpgsql;



Java Implementations

PWC 352 - Task 1 - PostgreSQL PL/Java Implementation

Similar implementation to PL/Perl, using the regular expression engine to match against words.

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

		List<String> found = new LinkedList<String>();

		for ( int i = 0; i < strings.length; i++ ) {
		    String current = strings[ i ];

		    Pattern regexp = Pattern.compile( current );

		    for ( int j = i + 1; j < strings.length; j++ ) {
				if ( regexp.matcher( strings[ j ] ).find() ) {
					found.add( current );
                }
		    }
		}


	return found.toArray( new String[0] );
    }


PWC 352 - Task 2 - PostgreSQL PL/Java Implementation

First of all, I compose the current string by concatenating the bits. Then I convert it into an integer, and check if it is a multiple of 5, in such case I add the value to the list found that is then returned.

    @Function( schema = "pwc352",
	       onNullInput = RETURNS_NULL,
	       effects = IMMUTABLE )
    public static final String[]  task2_pljava( String[] bits ) throws SQLException {
		logger.log( Level.INFO, "Entering pwc352.task2_pljava" );

		List<String> found = new LinkedList<String>();

		for ( int i = 0; i < bits.length; i++ ) {
		    String current = "0";

		    for ( int j = 0; j <= i; j++ ) {
				current += bits[ j ];
		    }

		    int val = Integer.parseInt( current, 2 );
		    if ( val % 5 == 0 )
				found.add( current );
		}

		return found.toArray( new String[0] );

    }


Python Implementations

PWC 352 - Task 1 - Python Implementation

Similar to the PL/Perl implementation.

import sys
import re

# task implementation
# the return value will be printed
def task_1( args ):
    found = []

    for i in range( 0, len( args ) ) :
        current = args[ i ]
        for j in range( i + 1, len( args ) ) :
            if re.match( current, args[ j ] ) :
                found.append( current )

    return found


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



PWC 352 - Task 2 - Python Implementation

Same implementation as in PL/Java, but please note how verbose it is to pass from a list to a mapped list.

import sys

# task implementation
# the return value will be printed
def task_2( args ):
    bits = list( map( int, args ) )
    found = []

    for i in range( 0, len( bits ) ) :
        current = ''.join( list( map( str, bits[ 0 : i + 1 ] ) ) )
        if int( current, 2 ) % 5 == 0 :
            found.append( current )

    return found


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



The article Perl Weekly Challenge 352: and here comes Christmas has been posted by Luca Ferrari on December 15, 2025