Perl Weekly Challenge 245: Hashes and Joins
This post presents my solutions to the Perl Weekly Challenge 245.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 245 - Task 1 - Raku
- PWC 245 - Task 1 - Raku (another implementation)
- PWC 245 - Task 2 - Raku
- PWC 245 - Task 1 in PostgreSQL PL/Perl
- PWC 245 - Task 2 in PostgreSQL PL/Perl
- PWC 245 - Task 1 in PostgreSQL PL/PgSQL
- PWC 245 - Task 2 in PostgreSQL PL/PgSQL
- PWC 245 - Task 1 in Python
- PWC 245 - Task 2 in Python
Raku Implementations
PWC 245 - Task 1 - Raku Implementation
The first task was about sorting a first hash of language names on the basis of a second array of language popularities. I decided to remap the languages into an hash, keyed by the popularity, and then reprint it after having sorted the keys.sub MAIN( :@langs where { @langs.elems == @langs.grep( * ~~ Str ).elems }
, :@popularity where { @popularity.elems == @langs.elems == @popularity.grep( * ~~ Int ).elems } ) {
my %sorted;
%sorted{ @popularity[ $_ ] } = @langs[ $_ ] for 0 ..^ @langs.elems;
my @output;
@output.push: %sorted{ $_ } for %sorted.keys.sort( { $^b <=> $^a } );
@output.join( ', ' ).say;
}
PWC 245 - Task 1 - Raku Implementation (another approach)
It is possible to use another approach to solve the problem:sub MAIN( :@langs where { @langs.elems == @langs.grep( * ~~ Str ).elems }
, :@popularity where { @popularity.elems == @langs.elems == @popularity.grep( * ~~ Int ).elems } ) {
( @langs [Z] @popularity ).sort( { $^b[1] <=> $^a[1] } ).map( *[ 0 ] ).join( ',' ).say;
}
What happens is:
[Z]
merges the arrays on a same index basis. The result is a set of arrays made by a language and its popularity;sort
does sort every element using the second (i.e., indexed as1
) element, that is the popularity;map
returns only the first element of each item, that is the language;join
andsay
does the printing.
PWC 245 - Task 2 - Raku Implementation
The second task was about finding out the max value of the concatenation of a given array of digits, assuming the value must be a multiple of3
.
sub MAIN( *@nums where { @nums.elems == @nums.grep( * ~~ Int ).elems
&& @nums.grep( 0 <= * <= 9 ).elems } ) {
my $largest = -1;
for @nums.permutations {
my $value = $_.join.Int;
next if $value !%% 3;
$largest = $value if ( $value > $largest );
}
$largest.say;
}
PL/Perl Implementations
PWC 245 - Task 1 - PL/Perl Implementation
Same implementation as in Raku.CREATE OR REPLACE FUNCTION
pwc245.task1_plperl( text[], int[] )
RETURNS SETOF text
AS $CODE$
my ( $langs, $popularity ) = @_;
die "Not same length arrays!" if ( $langs->@* != $popularity->@* );
my $sorting = {};
for my $index ( 0 .. $popularity->@* - 1 ) {
$sorting->{ $popularity->[ $index ] } = $langs->[ $index ];
}
for ( sort { $b <=> $a } $popularity->@* ) {
return_next( $sorting->{ $_ } );
}
return undef;
$CODE$
LANGUAGE plperl;
PWC 245 - Task 2 - PL/Perl Implementation
This time I had to useAlgorithm::Combinatorics
to get a quick access to a permutations
method.
CREATE OR REPLACE FUNCTION
pwc245.task2_plperl( int[] )
RETURNS int
AS $CODE$
use Algorithm::Combinatorics qw/ permutations /;
my ( $digits ) = @_;
die "Digits must be between 0 and 9" if ( grep( { $_ > 9 || $_ < 0 } $digits->@* ) );
my $result = -1;
for my $k ( 0 .. $digits->@* ) {
my $permutations = permutations( \ $digits->@*, $k );
while ( my $iter = $permutations->next ) {
my $value = join('', $iter->@* );
next if ( $value % 3 != 0 );
$result = $value if ( $value > $result );
}
}
return $result;
$CODE$
LANGUAGE plperlu;
PostgreSQL Implementations
PWC 245 - Task 1 - PL/PgSQL Implementation
This task is quite simple: I canunnest
the arrays, joining them, sorting by popularity and then filtering to get distinct values. In other words, it can be done with a single query.
CREATE OR REPLACE FUNCTION
pwc245.task1_plpgsql( langs text[], popularity int[] )
RETURNS SETOF text
AS $CODE$
WITH sorting AS (
SELECT l
FROM unnest( langs ) l
, unnest( popularity ) p
ORDER BY p DESC
)
SELECT distinct( l )
FROM sorting;
$CODE$
LANGUAGE sql;
PWC 245 - Task 2 - PL/PgSQL Implementation
Doing permutations in SQL is quite hard, and requires a recursive CTE. Therefore, I cheat here and use the Perl implementation!CREATE OR REPLACE FUNCTION
pwc245.task2_plpgsql( digits int[] )
RETURNS int
AS $CODE$
SELECT pwc245.task2_plperl( digits );
$CODE$
LANGUAGE sql;
Python Implementations
PWC 245 - Task 1 - Python Implementation
The idea is the same as in Raku, but the arrays are two command line strings with a pipe separator.import sys
# task implementation
def main( argv ):
langs = argv[ 0 ].split( "|" )
popularity = list( map( int, argv[1].split( "|" ) ) )
sorting = {}
for i in range( 0, len( popularity ) ):
sorting[ langs[ i ] ] = popularity[ i ]
for v in sorted( sorting.items(), key=lambda x: x[1], reverse=True ):
print( v[0] )
# invoke the main without the command itself
if __name__ == '__main__':
main( sys.argv[ 1: ] )
PWC 245 - Task 2 - Python Implementation
The idea is the same as in Raku, but to get the permutations I need an external library.import sys
from itertools import permutations
# task implementation
def main( argv ):
digits = list( map( int, argv ) )
result = -1
for p in permutations( digits ):
value = int( "".join( map( str, p ) ) )
if value % 3 != 0:
continue
if value > result:
result = value
print( result )
# invoke the main without the command itself
if __name__ == '__main__':
main( sys.argv[ 1: ] )