Perl Weekly Challenge 273: quite easy!
This post presents my solutions to the Perl Weekly Challenge 273.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 273 - Task 1 - Raku
- PWC 273 - Task 2 - Raku
- PWC 273 - Task 1 in PostgreSQL PL/Perl
- PWC 273 - Task 2 in PostgreSQL PL/Perl
- PWC 273 - Task 1 in PostgreSQL PL/PgSQL
- PWC 273 - Task 2 in PostgreSQL PL/PgSQL
- PWC 273 - Task 1 in PL/Java
- PWC 273 - Task 2 in PL/Java
- PWC 273 - Task 1 in Python
- PWC 273 - Task 2 in Python
Raku Implementations
PWC 273 - Task 1 - Raku Implementation
The first task was about computing the percentage of occurrency of a given char in a given string.sub MAIN( Str $string, Str $char where { $char.chars == 1 } ) {
( $string.comb.grep( * ~~ $char ).elems / $string.comb.elems * 100 ).Rat.round.say;
}
A one liner does suffice!
PWC 273 - Task 2 - Raku Implementation
See if a given string contains ab
and not any a
following the b
.
sub MAIN( Str $string where { $string.chars > 0 } ) {
'True'.say and exit if ( $string ~~ / b / && $string !~~ / b .* a / );
'False'.say;
}
A double pattern matching solves the problem.
PL/Perl Implementations
PWC 273 - Task 1 - PL/Perl Implementation
Similar to the Raku one.CREATE OR REPLACE FUNCTION
pwc273.task1_plperl( text, text )
RETURNS int
AS $CODE$
use POSIX;
my ( $string, $char ) = @_;
die "Pass a single char!" if ( length( $char ) != 1 );
return 0 if $string !~ / $char /x;
return POSIX::ceil( ( scalar( grep { $_ eq $char } split //, $string ) / scalar( split //, $string ) * 100 ) );
$CODE$
LANGUAGE plperlu;
Note the usage of
POSIX::ceil
to make the percentage the desired integer value, and hence the need for the untrusted language.
PWC 273 - Task 2 - PL/Perl Implementation
A double pattern matching solves the problem.CREATE OR REPLACE FUNCTION
pwc273.task2_plperl( text )
RETURNS boolean
AS $CODE$
my ( $string ) = @_;
return 1 if ( $string =~ / b /x and $string !~ / b .* a /x );
return 0;
$CODE$
LANGUAGE plperl;
PostgreSQL Implementations
PWC 273 - Task 1 - PL/PgSQL Implementation
A single nested query does the trick.CREATE OR REPLACE FUNCTION
pwc273.task1_plpgsql( s text, c char )
RETURNS int
AS $CODE$
WITH letters AS ( SELECT v FROM regexp_split_to_table( s, '' ) v )
, matches AS ( SELECT v FROM letters v WHERE v = c )
, c_l AS ( SELECT count(*) as x FROM letters )
, c_m AS ( SELECT count(*) as x FROM matches )
SELECT m.x::numeric / l.x::numeric * 100
FROM c_l l , c_m m;
$CODE$
LANGUAGE sql;
The casting between
numeric
and int
is already ceiled.
PWC 273 - Task 2 - PL/PgSQL Implementation
Another single query to apply the double pattern matching.CREATE OR REPLACE FUNCTION
pwc273.task2_plpgsql( s text )
RETURNS boolean
AS $CODE$
WITH has_b AS ( SELECT v FROM regexp_count( s, 'b' ) v )
, has_b_without_trailing_a AS ( SELECT v FROM regexp_count( s, 'b.*a' ) v )
SELECT CASE b.v WHEN NULL THEN false ELSE true END
FROM has_b b, has_b_without_trailing_a a
WHERE a.v = 0 AND b.v >= 1;
$CODE$
LANGUAGE sql;
Java Implementations
PWC 273 - Task 1 - PostgreSQL PL/Java Implementation
Even if not required for this application, use the stream API to count the number of characters that are within the given string.public class Task1 {
private final static Logger logger = Logger.getAnonymousLogger();
@Function( schema = "pwc273",
onNullInput = RETURNS_NULL,
effects = IMMUTABLE )
public static final int task1_pljava( String s, String c ) throws SQLException {
logger.log( Level.INFO, "Entering pwc273.task1_pljava" );
if ( c.length() != 1 )
throw new SQLException( "Need a single char!" );
final int[] values = new int[]{ 0, 0 };
values[ 1 ] = s.length();
Stream.of( s.split( "" ) )
.forEach( cc -> {
if ( cc.equals( c ) )
values[ 0 ]++;
} );
return (int) Math.round( (double) values[ 0 ] / values[ 1 ] * 100 );
}
}
PWC 273 - Task 2 - PostgreSQL PL/Java Implementation
Same as in other implementations: apply a double pattern matching.public class Task2 {
private final static Logger logger = Logger.getAnonymousLogger();
@Function( schema = "pwc273",
onNullInput = RETURNS_NULL,
effects = IMMUTABLE )
public static final boolean task2_pljava( String s ) throws SQLException {
logger.log( Level.INFO, "Entering pwc273.task2_pljava" );
Pattern p1 = Pattern.compile( "b" );
Pattern p2 = Pattern.compile( "b.*a" );
return p1.matcher( s ).find() && ! p2.matcher( s ).find();
}
}
Python Implementations
PWC 273 - Task 1 - Python Implementation
Almost a one liner, with the same logic as in Perl.import sys
# task implementation
# the return value will be printed
def task_1( args ):
s = args[ 0 ]
c = args[ 1 ]
return round( len( list( filter( lambda x: x == c, s ) ) ) / len( s ) * 100 )
# invoke the main without the command itself
if __name__ == '__main__':
print( task_1( sys.argv[ 1: ] ) )
PWC 273 - Task 2 - Python Implementation
A double pattern matching.import sys
import re
# task implementation
# the return value will be printed
def task_2( args ):
s = args[ 0 ]
p1 = re.compile( 'b' )
p2 = re.compile( 'b.*a' )
return p1.search( s ) and not p2.search( s )
# invoke the main without the command itself
if __name__ == '__main__':
print( task_2( sys.argv[ 1: ] ) )
Here I spent too much time since I forgot that
match
anchors to the beginning of the string, while search
does not.