Perl Weekly Challenge 366: what time is it?

This post presents my solutions to the Perl Weekly Challenge 366.
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:

Raku Implementations

PWC 366 - Task 1 - Raku Implementation

The first task was to find out if a given list of strings are prefixes of the last word.

sub MAIN( *@words ) {
    my $string = @words[ * - 1 ];
    my @matches;

    for 0 ..^ @words.elems - 1 {
		my $prefix = @words[ $_ ];
		@matches.push: $prefix if $string ~~ / ^ $prefix  /;
    }

    @matches.elems.say;
}



This is quite simple: I iterate over all the words but the last one, and check with a regular expression if any prefix is applicable to the given word. Last, I count how many items I’ve found.

PWC 366 - Task 2 - Raku Implementation

The second task was about finding out how many valid HH::MM time strings can be composed when a ? (or more) wildcard is applied. This can be solved better with a regular expression, but I took an iterative approach.

sub MAIN( Str $str ) {
    say 0 and exit if $str !~~ / '?' /;

    my ( $hours, $minutes ) = $str.split( ':' );
    my ( $left, $right ) = $hours.comb;

    my ( @a, @b );
    if ( $left eq '?' ) {
		@a.push: [ 0, 1, 2 ];
    }
    else {
		@a.push: $left.Int;
    }

    if ( $right eq '?' ) {
		@b.push: $_ for 0 .. 9;
    }
    else {
		@b.push: $right.Int;
    }


    my @hours;
    @hours = ( @a X~ @b )>>.Int.Array.grep( * <= 23 );

    @a = ();
    @b = ();
    ( $left, $right ) = $minutes.comb;

    if ( $left eq '?' ) {
		@a.push: $_ for 0 .. 9;
    }
    else {
		@a.push: $left.Int;
    }

    if ( $right eq '?' ) {
		@b.push: $_ for 0 .. 9;
    }
    else {
		@b.push: $right.Int;
    }

    my @minutes = ( @a X~ @b )>>.Int.Array.grep( * <= 59 );

    my @valid-times;
    for @hours -> $h {
		for @minutes -> $m {
			@valid-times.push: "%02d:%02d".sprintf( $h, $m );
		}
    }


    @valid-times.elems.say;
}



The approach is this:
  • I split the given string into the leftmost part (hours) and the rightmost (minutes);
  • I split every obtained part into its own digits, and check if there is a wildcard in the leftmost and rightmost digit;
  • I use @a and @b to keep track of valid digits in every part, so that I can compose a @hours and @minutes array made by the actual digits substituted where wildcards are found;
  • I zip Z the results to compose the @valid-times array and then count how many items I’ve found.

PL/Perl Implementations

PWC 366 - Task 1 - PL/Perl Implementation

Same approach as in Raku, using a regular expression matching.

CREATE OR REPLACE FUNCTION
pwc366.task1_plperl( text[], text )
RETURNS int
AS $CODE$

   my ( $prefixes, $string ) = @_;

   my @matches;

   for my $current ( $prefixes->@* ) {
       if ( $string =~ / ^ $current /x ) {
       	  push @matches, $current;
       }
   }

   return scalar( @matches );

$CODE$
LANGUAGE plperl;



PWC 366 - Task 2 - PL/Perl Implementation

Same approach as in Raku.

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

   my ( $string ) = @_;

   my ( $hours, $minutes ) = split ':', $string;

   my ( $left, $right ) = split '', $hours;
   my @hours;
   my ( @a, @b );


   if ( $left eq '?' ) {
      push @a, $_ for ( 0 .. 2 );
   }
   else {
     push @a, $left;
   }

   if ( $right eq '?' ) {
      push @b, $_ for ( 0 .. 9 );
   }
   else {
      push @b, $right;
   }

   my @valid_hours;
   for my $l ( @a ) {
      for my $r ( @b ) {
      	  my $t = sprintf '%02d', $l, $r;
         push @valid_hours, $t if ( $t <= 23 );
      }
   }

   @a = ();
   @b = ();
    ( $left, $right ) = split '', $minutes;
    if ( $left eq '?' ) {
       push @a, $_ for ( 0 .. 5 );
    }
    else {
      push @a, $left;
    }

    if ( $right eq '?' ) {
       push @b, $_ for ( 0 .. 9 );
    }
    else {
       push @b, $right;
    }

    my @valid_minutes;
    for my $l ( @a ) {
       for my $r ( @b ) {
       	  my $t = sprintf '%02d', $l, $r;
          push @valid_minutes, $t if ( $t <= 59 );
       }
    }

    my @valid_times;
    for my $h ( @valid_hours ) {
       for my $m ( @valid_minutes ) {
       	  push @valid_times, "$h:$m";
       }
    }

   return scalar @valid_times;

$CODE$
LANGUAGE plperl;



The article Perl Weekly Challenge 366: what time is it? has been posted by Luca Ferrari on March 26, 2026