# Perl Weekly Challenge 252: doing math to get zero!

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

The first task was about summing the squares of special numbers within a given array. A special number is the one indexed so that the length of the array modulus the position of the number is good.

``````sub MAIN( *@nums where { @nums.elems == @nums.grep( * ~~ Int ).elems } ) {
@nums.kv.map( { @nums.elems %% ( \$^index + 1 ) ?? \$^value ** 2 !! 0  } ).sum.say;
}

``````

Here I use a little trick: `@nums.kv` returns a list of pairs, namely `\$^index` and `\$^value` with the value and indexe within the array. Therefore, Iām able to `map` to get a single line program.

## PWC 252 - Task 2 - Raku Implementation

The second task was about generating an array of the given size, so that the sum of all the elements drops to zero.

``````sub MAIN( \$n where { \$n >= 3 && \$n ~~ Int  } ) {
my @nums;

if \$n %% 2 {
@nums.push: \$_, \$_ * -1 for 1 .. ( \$n / 2 );
}
else {
@nums.push: \$_, \$_ * -1 for 1 .. ( ( \$n - 2 ) / 2 );
my \$next = @nums.max + 1;
@nums.push: \$next, \$next + 1, ( \$next + \$next + 1 ) * -1;
}

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

``````

The idea is that if the requested size is even, then I only need to add couple `i` and `-i`, so that all the sums are zero. If the requested size is odd, then I do the same antipairs addition, but keeps the last three elements of the array to fill. I fille two of the remainings with incremented integers, and the last one with the negative sum of the last twos.

# PL/Perl Implementations

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

Here I thought to use `map` against `each`, but this does not work as I was expecting, so I had to do a loop instead.

``````CREATE OR REPLACE FUNCTION
RETURNS int
AS \$CODE\$
my ( \$nums ) = @_;

my ( \$sum ) = 0;

for ( 0 .. \$nums->@* - 1 ) {
next if \$nums->@* % ( \$_ + 1 ) != 0;
\$sum += \$nums->@[ \$_ ] ** 2;
}

return( \$sum );
\$CODE\$
LANGUAGE plperl;

``````

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

The solution is the same as in Raku: I distinguish the odd/even cases.

``````CREATE OR REPLACE FUNCTION
RETURNS SETOF int
AS \$CODE\$
my ( \$size ) = @_;

die "Cannot have a size less than 3!" if ( \$size <= 3 );

if ( \$size % 2 == 0 ) {
for ( 1 .. \$size / 2 ) {
return_next( \$_ );
return_next( \$_ * -1 );
}
}
else {
for ( 1 .. ( \$size - 1 ) / 2 ) {
return_next( \$_ );
return_next( \$_ * -1 );
}

my \$next = int( \$size / 2 ) + 1;
return_next( \$next );
return_next( \$next + 1 );
return_next( ( \$next + \$next + 1 ) * -1 );
}

return undef;
\$CODE\$
LANGUAGE plperl;

``````

# PostgreSQL Implementations

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

The same approach as PL/Perl: I iterate over the array and keep track only of interesting numbers.

``````CREATE OR REPLACE FUNCTION
RETURNS int
AS \$CODE\$
DECLARE
sumx int := 0;
BEGIN

FOR i IN 1 .. array_length( nums, 1 ) LOOP
IF mod( array_length( nums, 1 ), i ) <> 0 THEN
CONTINUE;
END IF;

sumx := sumx + pow( nums[ i ], 2 );
END LOOP;

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

``````

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

The approach is yet the same as in Raku.

``````CREATE OR REPLACE FUNCTION
RETURNS SETOF int
AS \$CODE\$
DECLARE
next_value int;
BEGIN

IF size <= 3 THEN
RAISE 'Cannot work with a size less than 3!';
END IF;

IF mod( size, 2 ) = 0 THEN
FOR i IN 1 .. ( size / 2 ) LOOP
RETURN NEXT i;
RETURN NEXT (i * -1);
END LOOP;
ELSE
FOR i IN 2 .. ( size - 1 ) / 2  LOOP
RETURN NEXT i;
RETURN NEXT (i * -1);
END LOOP;

next_value := ( size - 1 ) / 2  + 1;
RETURN NEXT next_value;
RETURN NEXT next_value + 1;
RETURN NEXT ( next_value + next_value + 1 ) * -1;
END IF;
RETURN;
END
\$CODE\$
LANGUAGE plpgsql;

``````

# Python Implementations

## PWC 252 - Task 1 - Python Implementation

Same approach as in PL/Perl.

``````import sys

# the return value will be printed
def main( argv ):
nums = list( map( int, argv ) )
sum = 0
for i in range( 0, len( nums ) ):
if len( nums ) % ( i + 1 ) == 0:
sum += nums[ i ] ** 2;

return sum

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

``````

## PWC 252 - Task 2 - Python Implementation

Again, same approach as in Raku and other implementations.

``````import sys

# the return value will be printed
def main( argv ):
size = int( argv[ 0 ] )
nums = []

if size % 2 == 0:
for i in range( 1, size / 2 ):
nums.append( i )
nums.append( i * -1 )
else:
for i in range( 1, int( ( size - 1 ) / 2 ) ):
nums.append( i )
nums.append( i * -1 )

next = max( nums ) + 1
nums.append( next )
nums.append( next + 1 )
nums.append( ( next + next + 1 ) * -1 )

return nums

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

``````

# Java Implementations

## PWC 252 - Task 1 - Java Implementation

Same iterating approach as in PL/Perl.

``````public class ch_1 {
public static void main( String argv[] ) {
int sum = 0;
for ( int i = 0; i < argv.length; i++ ) {
if ( argv.length % ( i + 1 ) != 0 )
continue;

sum += Math.pow( Integer.parseInt( argv[ i ] ), 2 );
}

System.out.println( sum );
}
}

``````

## PWC 252 - Task 2 - Java Implementation

Again, the very same approach I used in all other implementations.

``````public class ch_2 {
public static void main( String argv[] ) throws Exception {
int size = Integer.parseInt( argv[ 0 ] );

if ( size <= 3 )
throw new Exception( "Cannot work with a size less than 3!" );

if ( size % 2 == 0 ) {
for ( int i = 1; i < size / 2 ; i++ ) {
}
}
else {
for ( int i = 1; i < ( size - 1 ) / 2 ; i++ ) {
}

int next = ( size - 1 ) / 2 + 1;
nums.add( ( next * 2 + 1 ) * -1 );
}

boolean printedOne = false;
for ( int i : nums ) {
System.out.print( i + ( printedOne ? ", " : "" ) );
printedOne = true;
}

System.out.println();
}
}

``````

The article Perl Weekly Challenge 252: doing math to get zero! has been posted by Luca Ferrari on January 15, 2024