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:
- PWC 252 - Task 1 - Raku
- PWC 252 - Task 2 - Raku
- PWC 252 - Task 1 in PostgreSQL PL/Perl
- PWC 252 - Task 2 in PostgreSQL PL/Perl
- PWC 252 - Task 1 in PostgreSQL PL/PgSQL
- PWC 252 - Task 2 in PostgreSQL PL/PgSQL
- PWC 252 - Task 1 in Python
- PWC 252 - Task 2 in Python
- PWC 252 - Task 1 in Java
- PWC 252 - Task 2 in Java
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 usemap
against each
, but this does not work as I was expecting, so I had to do a loop instead.
CREATE OR REPLACE FUNCTION
pwc252.task1_plperl( int[] )
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
pwc252.task2_plperl( int )
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
pwc252.task1_plpgsql( nums int[] )
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
pwc252.task2_plpgsql( size int )
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
# task implementation
# 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
# task implementation
# 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!" );
List<Integer> nums = new LinkedList<Integer>();
if ( size % 2 == 0 ) {
for ( int i = 1; i < size / 2 ; i++ ) {
nums.add( i );
nums.add( i * -1 );
}
}
else {
for ( int i = 1; i < ( size - 1 ) / 2 ; i++ ) {
nums.add( i );
nums.add( i * -1 );
}
int next = ( size - 1 ) / 2 + 1;
nums.add( next );
nums.add( next + 1 );
nums.add( ( next * 2 + 1 ) * -1 );
}
boolean printedOne = false;
for ( int i : nums ) {
System.out.print( i + ( printedOne ? ", " : "" ) );
printedOne = true;
}
System.out.println();
}
}