Perl Weekly Challenge 348.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 348.
Task 1: String Alike
Submitted by: Mohammad Sajid Anwar
You are given a string of even length.
Write a script to find out whether the given string can be split into
two halves of equal lengths, each with the same non-zero number of vowels.
Example 1
Input: $str = "textbook"
Output: false
1st half: "text" (1 vowel)
2nd half: "book" (2 vowels)
Example 2
Input: $str = "book"
Output: true
1st half: "bo" (1 vowel)
2nd half: "ok" (1 vowel)
Example 3
Input: $str = "AbCdEfGh"
Output: true
1st half: "AbCd" (1 vowel)
2nd half: "EfGh" (1 vowel)
Example 4
Input: $str = "rhythmmyth"
Output: false
1st half: "rhyth" (0 vowel)
2nd half: "mmyth" (0 vowel)
Example 5
Input: $str = "UmpireeAudio"
Output: false
1st half: "Umpire" (3 vowels)
2nd half: "eAudio" (5 vowels)
I find the length of the string, use substr to divide it in two,
and use tr to count vowewls. The result fits a 1.5-liner.
Examples:
perl -E '
for(@ARGV){$l=length($s=$_);$f=substr $s,0,$l/2,""; ($x,$y)=map{tr/aeiouAEIOU//d}$f,$s;
say "$_-> ", $l%2==0&&$x==$y?"T":"F"}
' textbook book AbCdEfGh rhythmmyth UmpireeAudio
Results:
textbook-> F
book-> T
AbCdEfGh-> T
rhythmmyth-> T
UmpireeAudio-> F
Notice that my results disagree with the problem statement in example 4, but I believe I have the correct result, as 0==0.
The full code is:
1 # Perl weekly challenge 348
2 # Task 1: String Alike
3 #
4 # See https://wlmb.github.io/2025/11/17/PWC348/#task-1-string-alike
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 S0 S1...
8 to check if string Sn can be split into equal length parts with the
9 same number of vowels
10 FIN
11 for(@ARGV){
12 my $length=length(my $second=$_);
13 my $first=substr $second,0,$length/2,"";
14 my ($vowels_first, $vowels_second)=
15 map{tr/aeiouAEIOU//d}$first, $second;
16 my $result= $length%2==0 && $vowels_first == $vowels_second?"True":"False";
17 say "$_-> $result";
18 }
19
Example:
./ch-1.pl textbook book AbCdEfGh rhythmmyth UmpireeAudio
Results:
textbook-> False
book-> True
AbCdEfGh-> True
rhythmmyth-> True
UmpireeAudio-> False
Task 2: Covert Time
Submitted by: Mohammad Sajid Anwar
You are given two strings, $source and $target, containing time in 24-hour
time form.
Write a script to convert the source into target by performing one of the
following operations:
1. Add 1 minute
2. Add 5 minutes
3. Add 15 minutes
4. Add 60 minutes
Find the total operations needed to get to the target.
Example 1
Input: $source = "02:30"
$target = "02:45"
Output: 1
Just one operation i.e. "Add 15 minutes".
Example 2
Input: $source = "11:55"
$target = "12:15"
Output: 2
Two operations i.e. "Add 15 minutes" followed by "Add 5 minutes".
Example 3
Input: $source = "09:00"
$target = "13:00"
Output: 4
Four operations of "Add 60 minutes".
Example 4
Input: $source = "23:45"
$target = "00:30"
Output: 3
Three operations of "Add 15 minutes".
Example 5
Input: $source = "14:20"
$target = "15:25"
Output: 2
Two operations, one "Add 60 minutes" and one "Add 5 minutes"
I first convert the time to minutes. I use modular arithmetic, for the case where the target is smaller than the source, i.e., I add a full day to the target. The number of add x minutes operations, is the integer division of the remaining time by x, after which the remaining becomes the residue of dividing by x. To minimize the total number of operations, I start with the largest interval (60) and finish with the smallest one (1). The result fits a two-liner.
Examples:
perl -MPOSIX=floor -E '
for my($x,$y)(@ARGV){($t,$u)=map{($h,$m)=split/:/;$h*60+$m}($x,$y);$d=($u-$t)%(24*60);
$o=0;$o+=$_ for map{($c, $d)=(floor($d/$_),$d%$_);$c}60,15,5,1;say "$x, $y -> $o"}
' 02:30 02:45 11:55 12:15 09:00 13:00 23:45 00:30 14:20 15:25
Results:
02:30, 02:45 -> 1
11:55, 12:15 -> 2
09:00, 13:00 -> 4
23:45, 00:30 -> 3
14:20, 15:25 -> 2
The full code is:
1 # Perl weekly challenge 348
2 # Task 2: Covert Time
3 #
4 # See https://wlmb.github.io/2025/11/17/PWC348/#task-2-covert-time
5 use v5.36;
6 use feature qw(try);
7 use POSIX qw(floor);
8 die <<~"FIN" unless @ARGV and @ARGV%2==0;
9 Usage: $0 S0 T0 S1 T1...
10 to find how many operations (add 60, 15, 5 or 1 minute) are necessary to convert
11 the source time Sn to the target time Tn. The times are specified in the HH::MM
12 24 hour format.
13 FIN
14 my @minutes_to_add=(60, 15, 5, 1);
15 for my($source, $target)(@ARGV){
16 try {
17 my($source_mins, $target_mins) = map {
18 die "Wrong format: $_" unless /^(\d?\d):(\d{2})$/;
19 my ($hours, $minutes) = ($1, $2);
20 die "Invalid hours: $hours" unless 0<=$hours<24;
21 die "Invalid minutes: $minutes" unless 0<=$minutes<60;
22 $hours*60+$minutes
23 } $source, $target;
24 my $difference = ($target_mins - $source_mins)%(24*60); # modulo one day
25 my $operations = 0;
26 my $count;
27 $operations += $_ for map{
28 ($count, $difference)=(floor($difference/$_), $difference%$_);
29 $count
30 } @minutes_to_add;
31 say "$source, $target -> $operations";
32 }
33 catch($e){warn $e}
34 }
Example:
./ch-2.pl 02:30 02:45 11:55 12:15 09:00 13:00 23:45 00:30 14:20 15:25
Results:
02:30, 02:45 -> 1
11:55, 12:15 -> 2
09:00, 13:00 -> 4
23:45, 00:30 -> 3
14:20, 15:25 -> 2
Examples with errors:
./ch-2.pl 24:30 02:45 11:60 12:15 9:00 13:0 2>&1
Results:
Invalid hours: 24 at ./ch-2.pl line 21.
Invalid minutes: 60 at ./ch-2.pl line 22.
Wrong format: 13:0 at ./ch-2.pl line 19.
/;