Perl Weekly Challenge 341: back from Japan
It has been a while since I committed something to the Weekly Challenge, and this is due to the fact that I spent the last weeks preparing, and most notably, enjoying, a trip to Japan with my family. This post presents my solutions to the Perl Weekly Challenge 341.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 341 - Task 1 - Raku
- PWC 341 - Task 2 - Raku
- PWC 341 - Task 1 in PostgreSQL PL/Perl
- PWC 341 - Task 2 in PostgreSQL PL/Perl
- PWC 341 - Task 1 in PostgreSQL PL/PgSQL
- PWC 341 - Task 2 in PostgreSQL PL/PgSQL
- PWC 341 - Task 1 in PL/Java
- PWC 341 - Task 2 in PL/Java
- PWC 341 - Task 1 in Python
- PWC 341 - Task 2 in Python
Raku Implementations
PWC 341 - Task 1 - Raku Implementation
The first task was about to remove all the words in a sentence that contain a given letter from a list.sub MAIN( Str $text, *@keys ) {
$text.say and exit( 0 ) unless ( @keys.elems );
my @words;
for $text.split( / \s+ / ) -> $current-word {
my $found = 0;
for @keys {
$found += $current-word.comb.grep( * ~~ $_ ).elems;
}
last if $found;
@words.push: $current-word;
}
@words.join( ' ' ).say;
}
A nested loop solve the problem, splitting the sentence into words and then checking every word against a list of keys.
PWC 341 - Task 2 - Raku Implementation
The second task was about reversing the leftmost part of a given string up to a given letter, concatenating it to the remaining part of the string.sub MAIN( Str $text, Str $prefix where { $text ~~ / $prefix / } ) {
my $index = $text.comb( :skip-empty ).first( * ~~ $prefix, :k );
( $text.comb[ 0 .. $index ].join.flip ~ $text.comb[ $index + 1 .. * - 1 ].join ).say;
}
I first search for the first index of the given char into the string, and then contanate the slices flipping the leftmost.
PL/Perl Implementations
PWC 341 - Task 1 - PL/Perl Implementation
Same approach as in Raku, with a nested loop.CREATE OR REPLACE FUNCTION
pwc341.task1_plperl( text, text[] )
RETURNS SETOF text
AS $CODE$
my ( $text, $keys ) = @_;
for my $word ( split /\s+/, $text ) {
my $found = 0;
for my $key ( $keys->@* ) {
$found += scalar grep { $_ eq $key } split( //, $word );
last if ( $found );
}
return_next( $word ) unless ( $found );
}
return undef;
$CODE$
LANGUAGE plperl;
PWC 341 - Task 2 - PL/Perl Implementation
Similar to the Raku approach, use a slicing and reverse the leftmost.CREATE OR REPLACE FUNCTION
pwc341.task2_plperl( text, text )
RETURNS text
AS $CODE$
my ( $text, $prefix ) = @_;
my $index = index( $text, $prefix );
return $index unless( $index );
my @chars = split //, $text;
return join( '',
reverse( @chars[ 0 .. $index ] ),
@chars[ $index + 1 .. $#chars ] );
$CODE$
LANGUAGE plperl;
PostgreSQL Implementations
PWC 341 - Task 1 - PL/PgSQL Implementation
Same approach as in the previous implementations, does a nested loop to get the words and check every letter to remove them from the list.CREATE OR REPLACE FUNCTION
pwc341.task1_plpgsql( sentence text, keys text[] )
RETURNS SETOF text
AS $CODE$
DECLARE
current_word text;
ko int;
k text;
BEGIN
FOR current_word IN SELECT w FROM regexp_split_to_table( sentence, '\s+' ) w LOOP
ko := 0;
FOREACH k IN ARRAY keys LOOP
IF current_word ~ k THEN
ko := ko + 1;
END IF;
END LOOP;
IF ko = 0 THEN
RETURN NEXT current_word;
END IF;
END LOOP;
RETURN;
END
$CODE$
LANGUAGE plpgsql;
PWC 341 - Task 2 - PL/PgSQL Implementation
A quite verbose approach to create two arrays with the parts of the string, and awhile
loop to reverse the leftmost.
CREATE OR REPLACE FUNCTION
pwc341.task2_plpgsql( word text, p text )
RETURNS text
AS $CODE$
DECLARE
i int;
j int;
tt text[];
r text := '';
BEGIN
i := position( p IN word );
tt := regexp_split_to_array( word, '' );
j := i;
WHILE i > 0 LOOP
r := r || tt[ i ];
i := i - 1;
END LOOP;
r := r || array_to_string( tt[ j + 1 : ], '' );
RETURN r;
END
$CODE$
LANGUAGE plpgsql;
Java Implementations
PWC 341 - Task 1 - PostgreSQL PL/Java Implementation
Similar approach as in other implementations, but this time I remove the wrong strings from the original list of words. public static final String[] task1_pljava( String sentence, String[] keys ) throws SQLException {
logger.log( Level.INFO, "Entering pwc341.task1_pljava" );
List<String> words = new LinkedList<String>();
for ( String w : sentence.split( "\\s+" ) )
words.add( w );
Iterator<String> iter = words.iterator();
while ( iter.hasNext() ) {
String current_word = iter.next();
boolean ok = true;
for ( String k : keys )
if ( current_word.contains( k ) )
ok = false;
if ( ! ok )
iter.remove();
}
String result[] = new String[ words.size() ];
int i = 0;
for ( String w : words )
result[ i++ ] = w;
return result;
}
PWC 341 - Task 2 - PostgreSQL PL/Java Implementation
In this case, I useStringBuilder
to perform the reverse()
of the leftmost string quite quickly.
public static final String task2_pljava( String word, String prefix ) throws SQLException {
logger.log( Level.INFO, "Entering pwc341.task2_pljava" );
int index = word.indexOf( prefix, 1 );
StringBuilder builder = new StringBuilder();
builder.append( word.substring( 0, index ) );
builder.reverse();
return builder.toString() + word.substring( index + 1 );
}
Python Implementations
PWC 341 - Task 1 - Python Implementation
Similar implementation to Raku.import sys
# task implementation
# the return value will be printed
def task_1( args ):
sentence = args[ 0 ]
keys = args[ 1 : ]
result = []
for word in sentence.split():
found = False
for k in keys:
if k in word:
found = True
if not found:
result.append( word )
return ' '.join( result )
# invoke the main without the command itself
if __name__ == '__main__':
print( task_1( sys.argv[ 1: ] ) )
PWC 341 - Task 2 - Python Implementation
Similar to the PL/Perl approach.import sys
# task implementation
# the return value will be printed
def task_2( args ):
word = args[ 0 ]
prefix = args[ 1 ]
index = word.index( prefix )
return word[ index : 0 : -1 ] + word[ index : ]
# invoke the main without the command itself
if __name__ == '__main__':
print( task_2( sys.argv[ 1: ] ) )