Perl Weekly Challenge 331.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 331.
Task 1: Last Word
Submitted by: Mohammad Sajid Anwar
You are given a string.
Write a script to find the length of last word in the given string.
Example 1
Input: $str = "The Weekly Challenge"
Output: 9
Example 2
Input: $str = " Hello World "
Output: 5
Example 3
Input: $str = "Let's begin the fun"
Output: 3
I make a list by splitting the input on space and print the length of the last element. I use a negative index to access arrays from the end. The result fits a half-liner.
Examples:
perl -E '
for(@ARGV){say "$_ -> ", length [split " "]->[-1]}
' "The Weekly Challenge" " Hello World " "Let's begin the fun"
Results:
The Weekly Challenge -> 9
Hello World -> 5
Let's begin the fun -> 3
These may fail with punctuation characters:
perl -E '
for(@ARGV){say "$_ -> ", length [split " "]->[-1]}
' "The Weekly Challenge." " Hello World. " "Let's begin the fun."
Results:
The Weekly Challenge. -> 10
Hello World. -> 6
Let's begin the fun. -> 4
Thus, I remove all non-word characters before computing the length:
perl -E '
for(@ARGV){say "$_ -> ", length [split " "]->[-1]=~s/\W//gr}
' "The Weekly Challenge." " Hello World. " "Let's begin the fun!"
Results:
The Weekly Challenge. -> 9
Hello World. -> 5
Let's begin the fun! -> 3
The full code is:
1 # Perl weekly challenge 331
2 # Task 1: Last Word
3 #
4 # See https://wlmb.github.io/2025/07/21/PWC331/#task-1-last-word
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 S1 S2...
8 to find the length of the last word of the strings Sn
9 FIN
10 for(@ARGV){
11 say "$_ -> ", # print the result
12 length # compute the length
13 [split " "] # separate into words
14 ->[-1] # choose last word
15 =~s/\W//gr # remove non-word characters
16 }
Examples:
./ch-1.pl "The Weekly Challenge" " Hello World " "Let's begin the fun" \
"The Weekly Challenge." " Hello World. " "Let's begin the fun!"
Results:
The Weekly Challenge -> 9
Hello World -> 5
Let's begin the fun -> 3
The Weekly Challenge. -> 9
Hello World. -> 5
Let's begin the fun! -> 3
Task 2: Buddy Strings
Submitted by: Mohammad Sajid Anwar
You are given two strings, source and target.
Write a script to find out if the given strings are Buddy Strings.
If swapping of a letter in one string make them same as the other
then they are `Buddy Strings`.
Example 1
Input: $source = "fuck"
$target = "fcuk"
Output: true
The swapping of 'u' with 'c' makes it buddy strings.
Example 2
Input: $source = "love"
$target = "love"
Output: false
Example 3
Input: $source = "fodo"
$target = "food"
Output: true
Example 4
Input: $source = "feed"
$target = "feed"
Output: true
I join the source and target using the $SUBSEP
($;
) special
variable and let the regular expression machine do the matching. The
regular expression
I use is /^(.*)(.)(.*)(.)(.*)$;\1\4\3\2\5$/
. The first part matches
the start ^
of the string, then an arbitrary, possibly empty string,
captured as group 1 (i.e.,
\1
), a single character (\2), another arbitrary string (\3), another
single character (\4) and a final arbitrary string (\5) followed by
the marker ($;
) for the end of the first string. Then the second part
should be the same string but with the second and fourth capture groups
permuted, i.e., \1\4\3\2\5
, followed by the end $
of the
string. It is the job of the regular expression matcher to choose
which characters go into each group when attempting the match. The
result yields a longish one-liner.
Examples:
perl -E '
for my($s,$t)(@ARGV){say"$s $t -> ",($j="$s$;$t")=~/^(.*)(.)(.*)(.)(.*)$;\1\4\3\2\5$/?"T":"F"}
' fuck fcuk love love fodo food feed feed
Results:
fuck fcuk -> T
love love -> F
fodo food -> T
feed feed -> T
The full code is:
1 # Perl weekly challenge 331
2 # Task 2: Buddy Strings
3 #
4 # See https://wlmb.github.io/2025/07/21/PWC331/#task-2-buddy-strings
5 use v5.36;
6 die <<~"FIN" unless @ARGV && @ARGV%2==0;
7 Usage: $0 S1 T1 S2 T2...
8 to find if target string Tn may be obtained from the source string Sn
9 by a single permutation of two characters.
10 FIN
11 for my($source, $target)(@ARGV){
12 say"$source $target -> ",
13 (my $joined="$source$;$target") # join source and target using special character
14 =~ # match to
15 /^ # start of source
16 (.*) # arbitrary string (group 1)
17 (.) # a single character to permute (group 2)
18 (.*) # arbitrary string (group 3)
19 (.) # second character to permute (group 4)
20 (.*) # arbitrary string (group 5)
21 $; # end of source
22 \1\4\3\2\5 # target is source with \2 and \4 permuted
23 $ # end of target
24 /x
25 ?"True":"False";
26 }
Examples:
./ch-2.pl fuck fcuk love love fodo food feed feed
Results:
fuck fcuk -> True
love love -> False
fodo food -> True
feed feed -> True
Notice that I allow interchanging non-contiguous letters. If only contiguous letters may be swapped then I should remove the middle capture group and renumber the others in the regular expression above.
/;