Perl Weekly Challenge 269: at the last time I did!

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

The first task was about finding out if, in a given array of integers, there are couples of values that once logically OR-ed made a value that in binary ends with at least one zero. This means that the ending result must be even.

sub MAIN( *@nums where { @nums.elems == @nums.grep( { $_ ~~ Int && $_ > 0 } ).elems } ) {
    my @couples;
    for 0 ..^ @nums.elems -> $i {
	for $i ^..^ @nums.elems -> $j {
	    @couples.push: [ @nums[ $i ], @nums[ $j ] ] if ( ( @nums[ $i ] +| @nums[ $j ] ) %% 2 );
	}
    }

    @couples.join( "\n" ).say;
}



PWC 269 - Task 2 - Raku Implementation

The second task was about splitting a given array of numbers into two different ones, when the next element is inserted in the first array or in the second depepending on which arrays has the greatest last element. In the end, the arrays are merged again and printed.

sub MAIN( *@nums
	  where { @nums.elems == @nums.grep( { $_ ~~ Int && $_ > 0 } ).elems
				  && @nums.elems > 2 } ) {

    my @array1;
    my @array2;

    @array1.push: @nums.shift;
    @array2.push: @nums.shift;

    while ( @nums ) {
	if ( @array1[ * - 1 ] > @array2[ * - 1 ] ) {
	    @array1.push: @nums.shift;
	}
	else {
	    @array2.push: @nums.shift;
	}
    }


    ( @array1, @array2 ).flat.join( ', ' ).say;

}



PL/Perl Implementations

Same implementation as in Raku.

PWC 269 - Task 1 - PL/Perl Implementation



CREATE OR REPLACE FUNCTION
pwc269.task1_plperl( int[] )
RETURNS SETOF int
AS $CODE$

   my ( $nums ) = @_;

   for my $i ( 0 .. $nums->@* - 1 ) {
       for my $j ( $i + 1 .. $nums->@* -1 ) {
       	   my $result = $nums->@[ $i ] | $nums->@[ $j ];
	   if ( $result % 2 == 0 ) {
	      return_next( $nums->@[ $i ] );
	      return_next( $nums->@[ $j ] );
	   }
       }
   }

   return undef;
$CODE$
LANGUAGE plperl;



PWC 269 - Task 2 - PL/Perl Implementation

Similar implementation as in Raku.

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

   my ( $nums ) = @_;

   my ( @array1, @array2 );
   my @nums = $nums->@*;

   push @array1, shift @nums;
   push @array2, shift @nums;

   while ( @nums ) {

   	 if ( $array1[ $#array1 ] > $array2[ $#array2 ] ) {
	    push @array1, shift @nums;
	 }
	 else {
	   push @array2, shift @nums;
	 }
   }

   return_next( $_ ) for ( @array1, @array2 );
   return undef;

$CODE$
LANGUAGE plperl;



PostgreSQL Implementations

PWC 269 - Task 1 - PL/PgSQL Implementation

A single query can solve the problem: joining the array unnested to a table with itself and selecting only values where the ored value is even.

CREATE OR REPLACE FUNCTION
pwc269.task1_plpgsql( nums int[] )
RETURNS SETOF int
AS $CODE$

   SELECT a, b
   FROM unnest( nums ) a
       , unnest( nums ) b
   WHERE
      a <> b
      AND
      mod( a | b, 2 ) = 0;
$CODE$
LANGUAGE sql;



PWC 269 - Task 2 - PL/PgSQL Implementation

The idea and implementation is the same as in PL/Perl.

CREATE OR REPLACE FUNCTION
pwc269.task2_plpgsql( nums int[] )
RETURNS SETOF int
AS $CODE$
DECLARE
	array1 int[];
	array2 int[];
	i int;
BEGIN

	i := 1;
	array1 := array_append( array1, nums[ 1 ] );
	array2 := array_append( array2, nums[ 2 ] );
	i := i + 2;

	WHILE i < array_length( nums, 1 ) LOOP
	      IF array1[ i - 2 ] > array2[ i - 1 ] THEN
	      	 array1 := array_append( array1, nums[ i ] );
	      ELSE
	        array2 := array_append( array2, nums[ i ] );
	      END IF;

	      I := I + 2;
	END LOOP;

	RETURN QUERY SELECT v
	       	     FROM unnest( array1 ) v
		     UNION
		     SELECT v
		     FROM unnest( array2 ) v;
END
$CODE$
LANGUAGE plpgsql;



Java Implementations

PWC 269 - Task 1 - PostgreSQL PL/Java Implementation

A nested loop approach.

public class Task1 {

    private final static Logger logger = Logger.getAnonymousLogger();

    @Function( schema = "pwc269",
	       onNullInput = RETURNS_NULL,
	       effects = IMMUTABLE )
    public static final int[] task1_pljava( int[] nums ) throws SQLException {

		List<Integer> couples = new LinkedList<Integer>();

		for ( int i = 0; i < nums.length; i++ )
		    for ( int j = i + 1; j < nums.length; j++ )
			if ( ( nums[ i ] | nums[ j ] ) % 2 == 0 ) {
			    couples.add( nums[ i ] );
			    couples.add( nums[ j ] );
			}

		int result[] = new int[ couples.size() ];
		int i = 0;
		for ( int x : couples ) {
		    result[ i++ ] = x;
		}

		return result;
    }
}



PWC 269 - Task 2 - PostgreSQL PL/Java Implementation

Same implementation as in PL/Perl.

public class Task2 {

    private final static Logger logger = Logger.getAnonymousLogger();

    @Function( schema = "pwc269",
	       onNullInput = RETURNS_NULL,
	       effects = IMMUTABLE )
    public static final int[] task2_pljava( int[] nums ) throws SQLException {
		List<Integer> left = new LinkedList<Integer>();
		List<Integer> right = new LinkedList<Integer>();

		left.add( nums[ 0 ] );
		right.add( nums[ 1 ] );

		for ( int i = 2; i < nums.length; i++ ) {
		    if ( left.get( left.size() - 1 ) > right.get( right.size() - 1 ) )
				left.add( nums[ i++ ] );
		    else
			right.add( nums[ i++ ] );
		}

		int result[] = new int[ left.size() + right.size() ];
		int i = 0;
		for ( int x : left )
		    result[ i++ ] = x;
		for ( int x : right )
		    result[ i++ ] = x;

		return result;
    }
}



Python Implementations

PWC 269 - Task 1 - Python Implementation

As in the other implementations, use a nested loop to scan thru the numbers.

import sys

task implementation

the return value will be printed

def task_1( args ): nums = list( map( int, args ) ) couples = []
for i in range( 0, len( nums ) ):
    for j in range ( i + 1, len( nums ) ):
        if ( nums[ i ] | nums[ j ] ) % 2 == 0 :
            couples.append( nums[ i ] )
            couples.append( nums[ j ] )

return couples

invoke the main without the command itself

if name == ‘main’: print( task_1( sys.argv[ 1: ] ) )



PWC 269 - Task 2 - Python Implementation

Similar, but much more verbose implementation than the Raku one.

import sys

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

    left = []
    right = []

    left.append( nums[ 0 ] )
    right.append( nums[ 1 ] )

    i = 2
    while i < len( nums ):
        if left[ len( left ) - 1 ] > right[ len( right ) - 1 ] :
            left.append( nums[ i ] )
        else:
            right.append( nums[ i ] )
        i += 1

    return ( left, right )


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



The article Perl Weekly Challenge 269: at the last time I did! has been posted by Luca Ferrari on May 19, 2024