Perl Weekly Challenge 186: zip and unicode

It is sad that, after more than three years of me doing Raku, I still don’t have any production code project to work on. Therefore, in order to keep my coding and Raku-ing (is that a term?) knowdledge, I try to solve every Perl Weekly Challenge tasks.

In the following, the assigned tasks for Challenge 186.

and for the sake of some Perl 5, let’s do some stuff also in PostgreSQL Pl/Perl:
Last, the solutions in PostgreSQL PL/PgSQL:

PWC 186 - Task 1

Given two lists, of identical size, zip them.
Raku has the Z zip operator that does just that, so my first attemp was:

sub MAIN() {
    my @a = < 1 2 3 4 >;
    my @b = < a b c d >;

    say |(|@a Z |@b);
}


One problem is that all the list have to be flattened by means of the pipe, this to ensure a single list is returned. One could also use some hyper operator, like the comma, with something like |( |@a >>,<< |@b), but as you can see, the flattening is still needed.

PWC 186 - Task 2

Make an UTF-8 based string printable: luckily every string in Raku has a method smaemark that provides a transformation from an UTF-8 char to an ascii one.

sub MAIN( Str $input ) {
    $input.samemark( 'aeiou' ).say;
}




PWC 186 - Task 1 in PostgreSQL PL/Perl

Here I need to implement a zip (anonymous) function that iterates over all elements of the two arrays provided as input and push one element at the time into a third, resulting, array.

CREATE OR REPLACE FUNCTION
pwc186.task1_plperl( text[], text[] )
RETURNS text[]
AS $CODE$
my ( $left, $right ) = @_;

my $zip = sub {
   my ( $left, $right ) = @_;
   my $zipped = [];

   while ( $left->@* ) {
         push $zipped->@*, shift $left->@*, shift $right->@*;
   }

   return $zipped;
  };

  return $zip->( $left, $right );
$CODE$
LANGUAGE plperl;



I use the shift command to get a value out of each array at the same time, so I don’t need to keep an index.

PWC 186 - Task 2 in PostgreSQL PL/Perl

Here I need to use a module, like Unicode::Normalize that can provide me a way to transform a string. In partricular, the NFD method splits the unicode characters in a base and an extension, so that I can keep in the result only simple chars.

CREATE OR REPLACE FUNCTION
pwc186.task2_plperl( text )
RETURNS text
AS $CODE$

use Unicode::Normalize;

my ( $input ) = @_;
my @chars;

my $nfd = NFD $input;
for ( $nfd =~ / (\X) /xg ) {
    $_ =~ / (.) /x;
    push @chars, $1;
}

return join('', @chars );
$CODE$
LANGUAGE plperlu;



I first get an NFD string, than I globally match against every expanded character (\X), and for every character I got only the first part. Such part is captured into $1 and pushed into the @chars array, that is then joined and returned to the caller.

PWC 186 - Task 1 in PostgreSQL PL/PgSQL

Using the FOREACH loop approach and the array_append function it is quite simple (but verbose) to implement the zipping:

CREATE OR REPLACE FUNCTION
pwc186.task1_plpgsql( l text[], r text[] )
RETURNS text[]
AS $CODE$
DECLARE
        res text[];

BEGIN
    FOR i IN 1 .. array_length( l, 1 ) LOOP
        res := array_append( res, l[ i ] );
        res := array_append( res, r[ i ] );
    END LOOP;

    RETURN res;
END
$CODE$
LANGUAGE plpgsql;



PWC 186 - Task 2 in PostgreSQL PL/PgSQL

Here I trickly just call the Perl implementation to handle unicode chars!

CREATE OR REPLACE FUNCTION
pwc186.task2_plpgsql( t text )
RETURNS text
AS $CODE$
BEGIN
        RETURN pwc186.task2_plperl( t );
END
$CODE$
LANGUAGE plpgsql;



The article Perl Weekly Challenge 186: zip and unicode has been posted by Luca Ferrari on October 10, 2022