Perl Weekly Challenge 366.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 366.

Task 1: Count Prefixes

Submitted by: Mohammad Sajid Anwar
You are given an array of words and a string (contains only
lowercase English letters).

Write a script to return the number of words in the given
array that are a prefix of the given string.

Example 1
Input: @array = ("a", "ap", "app", "apple", "banana"),
       $str = "apple"
Output: 4

Example 2
Input: @array = ("cat", "dog", "fish"), $str = "bird"
Output: 0

Example 3
Input: @array = ("hello", "he", "hell", "heaven", "he"),
       $str = "hello"
Output: 4

Example 4
Input: @array = ("", "code", "coding", "cod"),
       $str = "coding"
Output: 3

Example 5
Input: @array = ("p", "pr", "pro", "prog", "progr", "progra",
       "program"), $str = "program"
Output: 7


I assume the input is given in @ARGV as pairs of string. The first element of the pair contains the array as comma separated prefixes and the second is the string. For each prefix in the array I test the string with a regular expression that matches the prefix at the start of the string. I use this RE to grep all words and count those that succeed. The result fits a one-liner.

perl -E '
for my($a, $s)(@ARGV){say"$a; $s -> ",0+grep{$s=~/^$_/}split/,\s*/,$a;}
' "a, ap, app, apple, banana" apple \
  "cat, dog, fish" bird \
  "hello, he, hell, heaven, he" hello \
  ", code, coding, cod" coding \
  "p, pr, pro, prog, progr, progra, program" program

Results:

a, ap, app, apple, banana; apple -> 4
cat, dog, fish; bird -> 0
hello, he, hell, heaven, he; hello -> 4
, code, coding, cod; coding -> 3
p, pr, pro, prog, progr, progra, program; program -> 7

The full code is similar:

 1  # Perl weekly challenge 366
 2  # Task 1:  Count Prefixes
 3  #
 4  # See https://wlmb.github.io/2026/03/27/PWC366/#task-1-count-prefixes
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV && @ARGV%2==0;
 7      Usage: $0 A0 S0 A1 S1...
 8      where the string An is a comma separated list of possible
 9      prefixes. The result is the number of prefixes of An that
10      match the string Sn
11      FIN
12  for my($array, $string)(@ARGV){
13      say"$array; $string -> ",0+grep{$string=~/^$_/} split /,\s*/, $array;
14  }

Example:

./ch-1.pl "a, ap, app, apple, banana" apple \
          "cat, dog, fish" bird \
          "hello, he, hell, heaven, he" hello \
          ", code, coding, cod" coding \
          "p, pr, pro, prog, progr, progra, program" program

Results:

a, ap, app, apple, banana; apple -> 4
cat, dog, fish; bird -> 0
hello, he, hell, heaven, he; hello -> 4
, code, coding, cod; coding -> 3
p, pr, pro, prog, progr, progra, program; program -> 7

Task 2: Valid Times

Submitted by: Mohammad Sajid Anwar
You are given a time in the form ‘HH:MM’. The earliest
possible time is ‘00:00’ and the latest possible time
is ‘23:59’. In the string time, the digits represented
by the ‘?’ symbol are unknown, and must be replaced with
a digit from 0 to 9.

Write a script to return the count different ways we can
make it a valid time.

Example 1
Input: $time = "?2:34"
Output: 3

0 -> "02:34" valid
1 -> "12:34" valid
2 -> "22:34" valid

Example 2
Input: $time = "?4:?0"
Output: 12

Hours: tens digit ?, ones digit 4 -> can be 04, and 14 (2 possibilities)
Minutes: tens digit ?, ones digit 0 -> tens can be 0-5 (6 possibilities)

Total: 2 × 6 = 12

Example 3
Input: $time = "??:??"
Output: 1440

Hours: from 00 to 23 -> 24 possibilities
Minutes: from 00 to 59 -> 60 possibilities

Total: 24 × 60 = 1440

Example 4
Input: $time = "?3:45"
Output: 3

If tens digit is 0 or 1 -> any ones digit works, so 03 and 13 are valid
If tens digit is 2 -> ones digit must be 0-3, but here ones digit is 3, so 23 is valid

Therefore: 0,1,2 are all valid -> 3 possibilities

Example 5
Input: $time = "2?:15"
Output: 4

Tens digit is 2, so hours can be 20-23
Ones digit can be 0,1,2,3 (4 possibilities)

Therefore: 4 valid times

A very inefficient but simple approach is to iteratively replace the first unknown digit by each of the digits 0..9, and recurse over the resulting string, until there are no unknowns. Then we can test if the resulting time is valid and add 1 to a counter for each success. This yields a two-liner. I use the r flag of the substitute operator to produce non-destructive substitutions.

perl -E '
for(@ARGV){say"$_ -> ",c($_);}sub c($t){return v($t)unless$t=~/\?/;my $c=0;for(0..9){
$c+=c($t=~s/\?/$_/r);}return$c;}sub v($t){($h,$m)=split ":", $t;0<=$h<24 && 0<=$m<60;}
' "?2:34" "?4:?0" "??:??" "?3:45" "2?:15"

Results:

?2:34 -> 3
?4:?0 -> 12
??:?? -> 1440
?3:45 -> 3
2?:15 -> 4

A similar full code is:

 1  # Perl weekly challenge 366
 2  # Task 2:  Valid Times
 3  #
 4  # See https://wlmb.github.io/2026/03/27/PWC366/#task-2-valid-times
 5  use v5.36;
 6  use feature qw(try);
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 T0 T1...
 9      to find in how many ways we may get a valid time from Tn
10      by replacing question marks by digits
11      FIN
12  for(@ARGV){
13      try {
14          die "Invalid time: $_" unless /^(\d|\?){2}:(\d|\?){2}/;
15          say"$_ -> ",count($_);
16      }
17      catch($e){ warn $e; }
18  }
19  
20  sub count($time){
21      return valid($time) unless $time=~/\?/;
22      my $count=0;
23      for(0..9){
24          $count += count($time=~s/\?/$_/r);
25      }
26      return $count;
27  }
28  
29  sub valid($time){
30      my ($hour, $minute) = split ":", $time;
31      0<=$hour<24 && 0<=$minute<60;
32  }

Example:

./ch-2.pl "?2:34" "?4:?0" "??:??" "?3:45" "2?:15"

Results:

?2:34 -> 3
?4:?0 -> 12
??:?? -> 1440
?3:45 -> 3
2?:15 -> 4

A maybe faster but more complex program would work separately on hours and minutes and compute the result without generating all valid times. I make an array of results and their associated test. For example, ...4 2\?... means that if the hour starts with a two followed by a question mark, there are four possible hours, namely, 20, 21, 22 and 23.

 1  # Perl weekly challenge 366
 2  # Task 2:  Valid Times
 3  #
 4  # See https://wlmb.github.io/2026/03/27/PWC366/#task-2-valid-times
 5  use v5.36;
 6  use feature qw(try);
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 T0 T1...
 9      to find in how many ways we may get a valid time from Tn
10      by replacing question marks by digits
11      FIN
12  for(@ARGV){
13      try {
14          die "Invalid time: $_" unless /^(\d|\?){2}:(\d|\?){2}$/;
15          say "$_ -> ", count($_);
16      }
17      catch($e){ warn $e; }
18  }
19  
20  sub count($time){
21      state @htests=qw(24 \?\? 10 /[01]\?/ 4 2\? 0 [3-9]\? 2 \?[4-9] 3 \?[0-3]);
22      state $hmax=24;
23      state @mtests=qw(60 \?\? 10 /[0-5]\?/ 0 [6-9]\? 6 \?[0-9]);
24      state $mmax=60;
25      my ($hours, $minutes)=split ':', $time;
26      return count_aux($hours, $hmax, @htests)*count_aux($minutes, $mmax, @mtests);
27  }
28  
29  sub count_aux($num, $max, @tests){
30      for my ($result, $re)(@tests){
31          return $result if $num=~/^$re$/;
32      }
33      return 0 <= $num < $max;
34  }
35  

./ch-2a.pl "?2:34" "?4:?0" "??:??" "?3:45" "2?:15"

Results:

?2:34 -> 3
?4:?0 -> 12
??:?? -> 1440
?3:45 -> 3
2?:15 -> 4

/;

Written on March 27, 2026