Perl Weekly Challenge 369: string indexes
This post presents my solutions to the Perl Weekly Challenge 369.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 369 - Task 1 - Raku
- PWC 369 - Task 2 - Raku
- PWC 369 - Task 1 in PostgreSQL PL/Perl
- PWC 369 - Task 2 in PostgreSQL PL/Perl
- PWC 369 - Task 1 in PostgreSQL PL/PgSQL
- PWC 369 - Task 2 in PostgreSQL PL/PgSQL
- PWC 369 - Task 1 in PL/Java
- PWC 369 - Task 2 in PL/Java
- PWC 369 - Task 1 in Python
- PWC 369 - Task 2 in Python
Raku Implementations
PWC 369 - Task 1 - Raku Implementation
The first task was about transforming a given string into an hashtag like single word.sub MAIN( Str $title ) {
my @tags;
for $title.lc.split( / \s+ / ) -> $word {
next if $word !~~ / ^ <[a..z A..Z - ]>+ $ /;
my @letters = $word.comb.Array;
@letters[ 0 ] .= uc;
@tags.push: @letters.join;
}
say '#' ~ @tags.join;
}
The idea is to collect into
@tags all the words that can make up the final tag, then joining them.
PWC 369 - Task 2 - Raku Implementation
Given a string, a size and a filler, distribute the string into batches of the given size using the filler in the case the last part is not complete.sub MAIN( Str $string is copy, Int $size, Str $filler
where { $string.chars > 0 && $size > 0 && $filler.chars == 1 } ) {
$string.say and exit if ( $size > $string.chars );
while ( $string.chars !%% $size ) {
$string ~= $filler;
}
my @parts = $string.comb.rotor( $size );
@parts.join( ', ' ).say;
}
The idea is quite simple:
$string is increased in size by adding $filler unless the size of string is a multiple of the given size.
This way, I know in advance that splitting the string will result into all completed batches.
PL/Perl Implementations
PWC 369 - Task 1 - PL/Perl Implementation
Similar to the Raku implementation.CREATE OR REPLACE FUNCTION
pwc369.task1_plperl( text )
RETURNS text
AS $CODE$
my ( $string ) = @_;
my @tag;
for my $word ( split /\s+/, lc $string ) {
next if $word !~ / [a-zA-Z\-] /x;
my @letters = split //, $word;
$word = uc( $letters[ 0 ] ) . join( '', @letters[ 1 .. $#letters ] );
push @tag, $word;
}
return '#' . join( '', @tag );
$CODE$
LANGUAGE plperl;
PWC 369 - Task 2 - PL/Perl Implementation
Same idea of the Raku implementation.CREATE OR REPLACE FUNCTION
pwc369.task2_plperl( text, int, text )
RETURNS SETOF text
AS $CODE$
my ( $string, $size, $filler ) = @_;
while ( length( $string ) % $size != 0 ) {
$string .= $filler;
}
my $index = 0;
my @chars = split //, $string;
while ( $index <= length( $string ) ) {
return_next( join( '', @chars[ $index .. $index + $size - 1 ] ) );
$index += $size;
}
return undef;
$CODE$
LANGUAGE plperl;
PostgreSQL Implementations
PWC 369 - Task 1 - PL/PgSQL Implementation
Iterate over single words and their content to append every good piece to the tag to return.CREATE OR REPLACE FUNCTION
pwc369.task1_plpgsql( title text )
RETURNS text
AS $CODE$
DECLARE
current_word text;
current_tag text;
BEGIN
current_tag := '#';
for current_word in select v from regexp_split_to_table( title, '\s+' ) v loop
if array_length( regexp_matches( current_word, '[^a-zA-Z\-]'), 1 ) = 1 then
continue;
end if;
current_word := regexp_replace( current_word, '[-]', '', 'g' );
current_word := initcap( lower( current_word ) );
current_tag := current_tag || current_word;
end loop;
return current_tag;
END
$CODE$
LANGUAGE plpgsql;
PWC 369 - Task 2 - PL/PgSQL Implementation
Cheating, I call the PL/Perl implementation in here.CREATE OR REPLACE FUNCTION
pwc369.task2_plpgsql( t text, s int, f text )
RETURNS SETOF text
AS $CODE$
SELECT pwc369.task2_plperl( t, s, f );
$CODE$
LANGUAGE sql;
Java Implementations
PWC 369 - Task 1 - PostgreSQL PL/Java Implementation
Same approach as in Raku and Perl. public static final String task1_pljava( String title ) throws SQLException {
logger.log( Level.INFO, "Entering pwc369.task1_pljava" );
String tag = "#";
String regexp = "[a-zA-Z\\-]+";
Pattern pattern = Pattern.compile( regexp );
for ( String word : title.split( "\\s+" ) ) {
Matcher engine = pattern.matcher( word );
if ( ! engine.matches() )
continue;
if ( word.contains( "-" ) )
word = word.replaceAll( "-", "" );
tag += word.substring( 0, 1 ).toUpperCase() + word.substring( 1 ).toLowerCase();
}
return tag;
}
PWC 369 - Task 2 - PostgreSQL PL/Java Implementation
Similar approach as in Raku. public static final String[] task2_pljava( String string, int size, String filler ) throws SQLException {
logger.log( Level.INFO, "Entering pwc369.task2_pljava" );
List<String> result = new LinkedList<String>();
while ( string.length() % size != 0 )
string += filler;
int index = 0;
while ( index < string.length() ) {
result.add( string.substring( index, index + size ) );
index += size;
}
return (String[]) result.toArray( new String[0] );
}
Python Implementations
PWC 369 - Task 1 - Python Implementation
Same approach as in PL/Java.import sys
import re
# task implementation
# the return value will be printed
def task_1( args ):
words = list( args[ 0 ].lower().split() )
tag = '#'
pattern = re.compile( '[a-zA-Z\-]+' )
for w in words:
if not pattern.match( w ):
continue
while '-' in w:
w = w.replace( '-', '' )
tag += w[ 0 ].upper() + w[ 1: ].lower()
return tag
# invoke the main without the command itself
if __name__ == '__main__':
print( task_1( sys.argv[ 1: ] ) )
PWC 369 - Task 2 - Python Implementation
Use the same approach as in other implementations.import sys
# task implementation
# the return value will be printed
def task_2( args ):
string = args[ 0 ]
size = int( args[ 1 ] )
filler = args[ 2 ]
while len( string ) % size != 0 :
string += filler
parts = []
index = 0
while index < len( string ):
parts.append( ''.join( list( string[ index : index + size ] ) ) )
index += size
return parts
# invoke the main without the command itself
if __name__ == '__main__':
print( task_2( sys.argv[ 1: ] ) )