Perl Weekly Challenge 317.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 317.
Task 1: Acronyms
Submitted by: Mohammad Sajid Anwar
You are given an array of words and a word.
Write a script to return true if concatenating the first letter of each word
in the given array matches the given word, return false otherwise.
Example 1
Input: @array = ("Perl", "Weekly", "Challenge")
$word = "PWC"
Output: true
Example 2
Input: @array = ("Bob", "Charlie", "Joe")
$word = "BCJ"
Output: true
Example 3
Input: @array = ("Morning", "Good")
$word = "MM"
Output: false
I guess the easiest approach is to build the acronym and compare it to the tentative one. This fits a one-liner.
Example 1:
perl -E '
$x=shift; $y=join "",map{substr $_,0,1}@ARGV; say "W=$x, L=@ARGV -> ", $x eq $y?"True":"False";
' PWC Perl Weekly Challenge
Results:
W=PWC, L=Perl Weekly Challenge -> True
Example 2:
perl -E '
$x=shift; $y=join "",map{substr $_,0,1}@ARGV; say "W=$x, L=@ARGV -> ", $x eq $y?"True":"False";
' BCJ Bob Charlie Joe
Results:
W=BCJ, L=Bob Charlie Joe -> True
Example 3:
perl -E '
$x=shift; $y=join "",map{substr $_,0,1}@ARGV; say "W=$x, L=@ARGV -> ", $x eq $y?"True":"False";
' MM Morning Good
Results:
W=MM, L=Morning Good -> False
For the full code I add some checks and a normalization.
1 # Perl weekly challenge 317
2 # Task 1: Acronyms
3 #
4 # See https://wlmb.github.io/2025/04/14/PWC317/#task-1-acronyms
5 use v5.36;
6 die <<~"FIN" unless @ARGV >= 2;
7 Usage $0 T W1 W2...
8 to find if T is an acronym for the list of words W1 W2...
9 FIN
10 my $tentative=shift;
11 my $acronym=join "",map{substr $_,0,1}@ARGV;
12 say "Tentative=$tentative, Words=@ARGV -> ", lc $tentative eq lc $acronym?"True":"False";
Example:
./ch-1.pl PWC Perl Weekly Challenge
./ch-1.pl BCJ Bob Charlie Joe
./ch-1.pl MM Morning Good
Results:
Tentative=PWC, Words=Perl Weekly Challenge -> True
Tentative=BCJ, Words=Bob Charlie Joe -> True
Tentative=MM, Words=Morning Good -> False
Task 2: Friendly Strings
Submitted by: Mohammad Sajid Anwar
You are given two strings.
Write a script to return true if swapping any two letters in one
string match the other string, return false otherwise.
Example 1
Input: $str1 = "desc", $str2 = "dsec"
Output: true
Example 2
Input: $str1 = "fuck", $str2 = "fcuk"
Output: true
Example 3
Input: $str1 = "poo", $str2 = "eop"
Output: false
Example 4
Input: $str1 = "stripe", $str2 = "sprite"
Output: true
The two strings are friends if they have the same set of characters but there are exactly two differences between the strings, or they are equal but at least one character is duplicated, so it may be swapped with its duplicate without changing the string. Ignoring the last possibility yields a two-liner.
Example 1:
perl -E '
($p,$q)=@ARGV; @p=split "",$p; @q=split "",$q; $p[$_]eq$q[$_]||++$d for(0..@p-1);($r,$s)=
map{join "",sort{$a cmp $b}@$_}([@p],[@q]); say "@ARGV -> ", $r eq $s && $d==2?"True":"False";
' desc dsec
Results:
desc dsec -> True
Example 2:
perl -E '
($p,$q)=@ARGV; @p=split "",$p; @q=split "",$q; $p[$_]eq$q[$_]||++$d for(0..@p-1);($r,$s)=
map{join "",sort{$a cmp $b}@$_}([@p],[@q]); say "@ARGV -> ", $r eq $s && $d==2?"True":"False";
' fuck fcuk
Results:
fuck fcuk -> True
Example 3:
perl -E '
($p,$q)=@ARGV; @p=split "",$p; @q=split "",$q; $p[$_]eq$q[$_]||++$d for(0..@p-1);($r,$s)=
map{join "",sort{$a cmp $b}@$_}([@p],[@q]); say "@ARGV -> ", $r eq $s && $d==2?"True":"False";
' poo eop
Results:
poo eop -> False
Exmple 4:
perl -E '
($p,$q)=@ARGV; @p=split "",$p; @q=split "",$q; $p[$_]eq$q[$_]||++$d for(0..@p-1);($r,$s)=
map{join "",sort{$a cmp $b}@$_}([@p],[@q]); say "@ARGV -> ", $r eq $s && $d==2?"True":"False";
' stripe sprite
Results:
stripe sprite -> True
For the full code I add the degenerate case.
1 # Perl weekly challenge 317
2 # Task 2: Friendly Strings
3 #
4 # See https://wlmb.github.io/2025/04/14/PWC317/#task-2-friendly-strings
5 use v5.36;
6 use List::Util qw(uniq);
7 die <<~"FIN" unless @ARGV and @ARGV%2==0;
8 Usage: $0 S11 S12 S21 S22...
9 to find if strings Sn1 and Sn2 are friendly, i.e.,
10 match after one swap.
11 FIN
12 for my ($str1, $str2)(@ARGV){
13 my ($arr1, $arr2)=map {[split ""]}($str1, $str2);
14 my $differences=0;
15 $arr1->[$_] eq $arr2->[$_] || ++$differences for(0..$arr1->@*-1);
16 my ($sorted1, $sorted2) = map{join "",sort{$a cmp $b}@$_} ($arr1, $arr2);
17 my @uniq = uniq @$arr1;
18 my $result = ($sorted1 eq $sorted2 # same letters
19 &&
20 ($differences == 2 # exactly two differences
21 || ($differences == 0 && @uniq != @$arr1) # or repeated letter
22 )) ? "True" : "False";
23 say "$str1 $str2 -> $result";
24 }
Examples:
./ch-2.pl desc dsec fuck fcuk poo eop stripe sprite
Results:
desc dsec -> True
fuck fcuk -> True
poo eop -> False
stripe sprite -> True
Other examples:
./ch-2.pl Ah Ah Ahh Ahh
Results:
Ah Ah -> False
Ahh Ahh -> True
The last case is peculiar, in that we can swap the two h’s without changing the word, so both words agree after a single swap.
/;