# Perl Weekly Challenge 257: Post-Valentine Challenge

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

The first task was to remap an array of integers into an array where every value was the count of elements of the array lower than the current element value. This can be sovled with a single line in Raku:

``````sub MAIN( *@numbers where { @numbers.elems == @numbers.grep( * ~~ Int ).elems } ) {
@numbers.map( -> \$current { @numbers.grep( * < \$current ).elems } ).join( ', ' ).say;
}
``````

## PWC 257 - Task 2 - Raku Implementation

Given a matrix of integers, find out if the matrix can be reduced according to specific rules. The rules are not so clear to me, but essentially:
• every row must be either full of zero or the leftmost not zero element must be a one;
• every leftmost one in the row is called a leading one and must be rightmost of the leading ones of the above rows;
• the zero rows must be all at the bottom of the matrix.

``````sub MAIN() {
my \$M = [
[1, 1, 0],
[0, 1, 0],
[0, 0, 0]
];

my \$ok = True;
my @zero-rows;
for 0 ..^ \$M.elems -> \$row {
my \$first-in-row = Nil;

for 0 ..^ \$M[ \$row ].elems -> \$col {
next if \$M[ \$row ][ \$col ] == 0;
next if \$first-in-row;

\$first-in-row = \$M[ \$row ][ \$col ] if ! \$first-in-row;

if ( \$first-in-row == 1 ) {
@leadings.push: { row => \$row, col => \$col };
# if not other leadings, skip any check

\$ok = False and last if ( @leadings[ * - 2 ]<col> >= \$col && @leadings[ * - 2 ]<row> != ( \$row - 1 ) );
}
}

if ! \$first-in-row {
# the row was made by all zeros
@zero-rows.push: \$row;
# if this is the first zero row, cannot check anything
next if @zero-rows.elems <= 1;
# this is not the first zero row, so the previous row must be also zero!
\$ok = False if @zero-rows[ * - 2 ] != ( \$row - 1 );
}
elsif \$first-in-row != 1 {
\$ok = False;
}

'0'.say and exit if ( ! \$ok );
}

'1'.say; # here everything is fine
}

``````

I iterate on every row and column, and keep a `first-in-row` element that is valued only with the leftmost non zero value. Then, if such element is a one, it is also pushed to a `@leadings` array that keeps track of the rows with the leading values, storing a `Pair` with the row and column index. On the other hand, if the `first-in-row` is not valued, the row is filled by zeros, so append its index to the `@zero-rows` arraay. Then, I check if the `@zero-rows` array if consistent, as well as columns in `@leadings` go from left to right.

# PL/Perl Implementations

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

Really simple implementation.

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

my ( \$numbers ) = @_;

for my \$current ( \$numbers->@* ) {
return_next( scalar( grep( { \$_ < \$current } \$numbers->@* ) ) );
}

return undef;

\$CODE\$
LANGUAGE plperl;

``````

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

The implement follows the same reasoning of that in Raku.

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

my ( \$matrix ) = @_;

my \$ok = 1;
my @zero_rows;

my \$row ( 0 .. \$matrix->@* - 1 ) {
my \$first_in_row = undef;

for my \$col ( 0 .. \$matrix->@* - 1 ) {
next if \$matrix->[ \$row ][ \$col ] == 0;
next if \$first_in_row;

\$first_in_row = \$matrix->[ \$row ][ \$col ] if ( ! \$first_in_row );

# the first non-zero value of every row must be a one
\$ok = 0 and last if ( \$first_in_row != 1 );

push @leadings, { row => \$row, col => \$col };

}

if ( ! \$first_in_row ) {
# the row was filled with zeros
push @zero_rows, \$row;

next if @zero_rows <= 1;
\$ok = 0 and last if ( @zero_rows[ -1 ] != ( \$row - 1 ) );
}
elsif ( \$first_in_row == 1 ) {
\$ok = 0 and last if ( @leadings[ -2 ]->{ col } >= @leadings[ -1 ]->{ col }
|| @leadings[ -2 ]->{ row } != @leadings[ -1 ]->{ row } - 1 );
}

return \$ok if ! \$ok;
}

return \$ok;
return undef;

\$CODE\$
LANGUAGE plperl;

``````

# PostgreSQL Implementations

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

This can be sovled with a single query.

``````CREATE OR REPLACE FUNCTION
RETURNS SETOF int
AS \$CODE\$
select z
from unnest( numbers ) v,
lateral ( select count(x)
from unnest( numbers ) x
WHERE x < v ) as y(z);
\$CODE\$
LANGUAGE sql;

``````

Note the usage of lateral join to evaluate the current `v` element for every subquery.

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

Here I cheat, and use the PL/Perl implementation directly, because PL/PgSQL is really poor at handling matrixes.

``````CREATE OR REPLACE FUNCTION
RETURNS bool
AS \$CODE\$
\$CODE\$
LANGUAGE sql;

``````

# Java Implementations

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

The task needs to implement a `ResultSetProvider` since the function must return a single row for every evaluation.

``````public class Task1 implements ResultSetProvider {

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

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

}

public Task1( int[] nums ) {
numbers = nums;
}

private int[] numbers;

@Override
public boolean assignRowValues(ResultSet receiver, int currentRow)
throws SQLException {

if ( currentRow >= numbers.length )
return false;

int current = numbers[ currentRow  ];

int count = 0;
for ( int other : numbers )
if ( other < current )
count++;

return true;

}

@Override
public void close() { }

}

``````

The idea is that the function will create a `Task1` object that will store the input array of numbers, and then will produce every row thru the `assignRowValues()` function. This function, in turn, counts the number of elements less than the current one, dependent on the `currentRow` passed by the result set provider.

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

Here there is a complication: PL/Java cannot handle an `int[][]` as a matrix, thus I use the same trick I would do with PL/PgSQL, hence passing a linear array and a column size to split the linear array into a matrix.

``````public class Task2 {
private final static Logger logger = Logger.getAnonymousLogger();

@Function( schema = "pwc257",
onNullInput = RETURNS_NULL,
effects = IMMUTABLE )
public static final boolean task2_pljava( int[] matrix, int cols  ) throws SQLException {

boolean ok = false;
Integer current = null;

for ( int row = 0; row < matrix.length / cols ; row++ ) {
current = null;

for ( int col = 0; col < cols; col++ ) {

int element = matrix[ row * cols + col ];
if ( element == 0 || current != null )
continue;

current = element;
if ( current != 1 )
return false;

if ( leadings.size() <= 1 )
continue;

return false;
}

if ( current == null ) {
// all zero row

if ( zero_rows.size() <= 1 )
continue;

if ( zero_rows.get( zero_rows.size() - 2 ) != ( zero_rows.get( zero_rows.size() - 1) - 1 ) )
return false;
}
}

return true;

}
}

``````

The logic is the same used in PL/Perl and Raku.

# Python Implementations

## PWC 257 - Task 1 - Python Implementation

Same implementation as PL/Perl, with a lot more clutter to convert results into lists.

``````import sys

# the return value will be printed
output = []
numbers = list( map( int, args ) )
for current in numbers:
output.append( len( list( filter( lambda x: x < current, numbers ) ) ) )

return output

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

``````

## PWC 257 - Task 2 - Python Implementation

The same logic in all the other implementations, with the usage of a dictionary instead of an hash.

``````import sys

# the return value will be printed

ok = False
zero_rows = []

for row in range( 0, len( numbers ) ):
first_in_row = None

for col in range( 0, len( numbers[ row ] ) ):
if numbers[ row ][ col ] == 0:
continue

if first_in_row != None:
continue

first_in_row = numbers[ row ][ col ]

if first_in_row != 1:
return False

leadings.append( { 'row' : row, 'col' : col } )
continue

if leadings[ -2 ][ 'row' ] != ( row - 1 ) and leadings[ -2 ][ 'col' ] >= col:
return False

if first_in_row == None:
zero_rows.append( row )

if len( zero_rows ) <= 1:
continue
if zero_rows[ -2 ] != ( row - 1 ):
return False
elif first_in_row == 1:
if len( leadings ) <= 1:
continue
if leadings[ -2 ][ 'row' ] != leadings[ -1 ][ 'row' ] -1 and leadings[ -2 ][ 'col' ] >= leadings[ -1 ][ 'col' ]:
return False

return True

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

``````

The article Perl Weekly Challenge 257: Post-Valentine Challenge has been posted by Luca Ferrari on February 19, 2024