# Perl Weekly Challenge 262: another short one!

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

The first task was about computing the max counting among positive and negative integers.

``````sub MAIN( *@nums where { @nums.grep( * ~~ Int ).elems == @nums.elems } ) {
( @nums.grep( * >= 0 ).elems, @nums.grep( * < 0 ).elems ).max.say;
}

``````

## PWC 262 - Task 2 - Raku Implementation

The second task was to compute how many pairs of numbers are in a given array so that one is leftmost of the other, and the indexes of their positions multiplied together are a multiple of a given value `k`.

``````sub MAIN( Int \$k where { \$k != 0 },
*@nums where { @nums.grep( * ~~ Int ).elems == @nums.elems } ) {

my @pairs;

for 0 ..^ @nums.elems -> \$i {
for \$i ^..^ @nums.elems -> \$j {
next if ( \$i * \$j ) !%% \$k;
next if @nums[ \$i ] != @nums[ \$j ];
@pairs.push: [ \$i, \$j ];
}
}

@pairs.elems.say;
}

``````

# PL/Perl Implementations

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

A very simple implementation using again `grep`.

``````CREATE OR REPLACE FUNCTION
RETURNS int
AS \$CODE\$

my ( \$nums ) = @_;

my ( \$positives, \$negatives ) =
( scalar( grep { \$_ >= 0 } \$nums->@* ),
scalar( grep { \$_ < 0 } \$nums->@* ) );

return \$positives >= \$negatives
? \$positives
:  \$negatives;

\$CODE\$
LANGUAGE plperl;

``````

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

A nested loop to solve the trick.

``````CREATE OR REPLACE FUNCTION
RETURNS int
AS \$CODE\$

my ( \$k, \$nums ) = @_;

my @pairs;
for my \$i ( 0 .. \$nums->@* - 1 ) {
for my \$j ( \$i + 1 .. \$nums->@* - 1 ) {
next if ( \$i * \$j ) % \$k != 0;
next if ( \$nums->@[ \$i ] != \$nums->@[ \$j ] );
push @pairs, [ \$i, \$k ];
}
}

return scalar @pairs;
\$CODE\$
LANGUAGE plperl;

``````

# PostgreSQL Implementations

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

A single query with a few subqueries to compute the max value.

``````CREATE OR REPLACE FUNCTION
RETURNS int
AS \$CODE\$

WITH positives AS (
SELECT count( v ) as c
FROM unnest( nums ) v
WHERE  v >= 0
), negatives AS (
SELECT count( v ) as c
FROM unnest( nums ) v
WHERE  v < 0
)
, b AS (
SELECT c as v FROM positives
UNION
SELECT c as v FROM negatives
)
SELECT max( b.v )
FROM b;
\$CODE\$
LANGUAGE sql;

``````

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

A nested loop to count the pairs. Please note that in SQL the indexes starts from `1`, so the same input does not provide the same result as in other languages.

``````CREATE OR REPLACE FUNCTION
pwc262.task2_plpgsql( k int, nums int[] )
RETURNS int
AS \$CODE\$
DECLARE
pairs_count int := 0;
BEGIN
FOR i IN 1 .. array_length( nums, 1 )  LOOP
FOR j IN ( i + 1 ) .. array_length( nums, 1 )  LOOP
IF nums[ i ] <> nums[ j ] THEN
CONTINUE;
END IF;

IF mod( i * j, k ) <> 0 THEN
CONTINUE;
END IF;

pairs_count := pairs_count + 1;
END LOOP;
END LOOP;

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

``````

# Java Implementations

## PWC 262 - Task 1 - PostgreSQL PL/Java Implementation

Very simple implementation with a single loop that counts the values depending on their “type”.

``````public class Task1 {

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

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

int positives = 0;
int negatives = 0;

for ( int current : nums )
if ( current >= 0 )
positives++;
else
negatives++;

return positives >= negatives ? positives : negatives;

}
}

``````

This can be solved also using streams, for example:

``````    public static final int task1_pljava( int[] nums ) throws SQLException {
final int[] results = new int[]{ 0, 0 };

Arrays.stream( nums )
.forEach( current -> {
int index = current >= 0 ? 0 : 1;
results[ index ]++;
} );

return results[ 0 ] >= results[ 1 ] ? results[ 0 ] : results[ 1 ];

}
``````

The idea is:
• convert the `nums` array to a stream using `Arrays.stream`
• `forEach` value, placed into `current` I check if the value is positive or not, and extract an `index`, either zero or one
• increment the location of `results` accordingly, with `results[ 0 ]` that represents the positive values and `results[ 1 ]` that represents negative values.

## PWC 262 - Task 2 - PostgreSQL PL/Java Implementation

A nested loop even in this implementation.

``````public class Task2 {

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

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

int pairs = 0;
for ( int i = 0; i < nums.length; i++ )
for ( int j = i + 1; j < nums.length; j++ )
if ( nums[ i ] != nums[ j ]
|| ( i * j ) % k != 0 )
continue;
else
pairs++;

return pairs;

}
}

``````

It is possible to implement this with stream, for example:

``````public class Task2 {

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

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

final int pairs[] = new int[]{ 0 };
IntStream.range( 0, nums.length )
.forEach( i -> {
IntStream.range( i + 1, nums.length )
.forEach( j -> {
if ( nums[ i ] == nums[ j ]
&& ( i * j ) % k == 0 )
pairs[ 0 ]++;
} );
} );

return pairs[ 0 ];

}
}

``````

The idea is as follows:
• the `pairs` array is a monodimensional array used only to access a counter from within the streams;
• the outer `IntStream.range` loops on the `i` variable, and `forEach` value opens another stream;
• the inner `IntStream.range` loops over the `i+1` value on `j` and `forEach` value tests if the array values are the same and satisfy the aim of the task
• if the current pair is fine, the counter is incremented.

# Python Implementations

## PWC 262 - Task 1 - Python Implementation

Same approach used in Java here: counting two types of values, but this time with a `filter` (like `grep` in Perl).

``````import sys

# the return value will be printed
nums = list( map( int, args ) )
positives = len( list( filter( lambda x: True if x >= 0 else False, nums ) ) )
negatives = len( list( filter( lambda x: True if x < 0  else False, nums ) ) )

return positives if positives >= negatives else negatives

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

``````

## PWC 262 - Task 2 - Python Implementation

A nested loop.

``````import sys

# the return value will be printed
k     = int( args[ 0 ] )
nums  = list( map( int, args[ 1: ] ) )
pairs = []

for i in range( 0, len( nums ) ):
for j in range( i + 1, len( nums ) ):
if nums[ i ] != nums[ j ] or ( i * j ) % k != 0:
continue
else:
pairs.append( [ i, j ] )

return len( pairs )

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

``````

The article Perl Weekly Challenge 262: another short one! has been posted by Luca Ferrari on March 26, 2024