Perl Weekly Challenge 385.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 385.
Task 1: Uncommon Words
Submitted by: Mohammad Sajid Anwar
You are given two sentences.
Write a script to return list of all uncommon words, order
is not important.
Example 1
Input: $sentence1 = "apple banana apple"
$sentence2 = "banana orange"
Output: ("orange")

Example 2
Input: $sentence1 = "cat dog"
$sentence2 = "bird fish"
Output: ("cat", "dog", "bird", "fish")

Example 3
Input: $sentence1 = "the quick brown fox"
$sentence2 = "the quick"
Output: ("brown", "fox")

Example 4
Input: $sentence1 = "hello"
$sentence2 = "hello"
Output: ()

Example 5
Input: $sentence1 = "blue blue red"
$sentence2 = "red green green yellow"
Output: ("yellow")

I can use hashes to count the words in both sets. Uncommon words would have a count of 1. The code fits a 2-liner.
Examples:
perl -E '
for my($l, $m)(@ARGV){my%h;++$h{$_}for split" ","$l $m";@o=
grep{$h{$_}==1}keys %h;say "$l; $m -> @o"}
' "apple banana apple" "banana orange" "cat dog" "bird fish" \
"the quick brown fox" "the quick" "hello" "hello" \
"blue blue red" "red green green yellow"
Results:
apple banana apple; banana orange -> orange
cat dog; bird fish -> fish bird cat dog
the quick brown fox; the quick -> fox brown
hello; hello ->
blue blue red; red green green yellow -> yellow
The full code is
1 # Perl weekly challenge 385
2 # Task 1: Uncommon Words
3 #
4 # See https://wlmb.github.io/2026/08/03/PWC385/#task-1-uncommon-words
5 use v5.36;
6 die <<~"FIN" unless @ARGV && @ARGV %2 == 0;
7 Usage: $0 X0 Y0 X1 Y1...
8 to find non-repeated words in the strings Xn and Yn.
9 FIN
10 for my($sentence1, $sentence2)(@ARGV){
11 my %count;
12 ++$count{$_} for split" ","$sentence1 $sentence2";
13 my @out = grep{$count{$_}==1} keys %count;
14 say "$sentence1; $sentence2 -> (@out)";
15 }
Example:
./ch-1.pl "apple banana apple" "banana orange" "cat dog" "bird fish" \
"the quick brown fox" "the quick" "hello" "hello" \
"blue blue red" "red green green yellow"
Task 2: Outermost Parentheses
Submitted by: Mohammad Sajid Anwar You are given a valid parentheses string.
Write a script to return the string after removing the outermost parentheses of every primitive string in the primitive decomposition of the given string.
Example 1 Input: $str = “()()()” Output: “”
Primitive Decomposition: “()” + “()” + “()”
Example 2 Input: $str = “(((())))” Output: “((()))”
Primitive Decomposition: “(((())))”
Example 3 Input: $str = “(()())(())” Output: “()()()”
Primitive Decomposition: “(()())” + “(())”
Example 4 Input: $str = “()((()))()” Output: “(())”
Primitive Decomposition: “()” + “((()))” + “()”
Example 5 Input: $str = “(()(()))(()())” Output: “()(())()()”
Primitive Decomposition: “(()(()))” + “(()())” #+endexample
I make a Schwartzian transform to count the the depth of every parenthesis and remove those at depth 0. The results fits a 2-liner.
Examples:
perl -E '
for(@ARGV){@x=split"",$_;$c=0;say"$_ -> ",map{$_->[0]}grep
{$_->[1]>0}map{/\(/?[$_,$c++]:[$_,--$c]} split "",$_}
' "()()()" "(((())))" "(()())(())" "()((()))()" "(()(()))(()())"
Results:
()()() ->
(((()))) -> ((()))
(()())(()) -> ()()()
()((()))() -> (())
(()(()))(()()) -> ()(())()()
This worked as some hidden assumptions held, i.e., the count was never negative and no characters were present but opening and closing parenthesis.
A more robust solution may be obtained by using
Text::Balanced= to extract balanced parenthesized
sub-expressions, though the solution is much more complex.
1 # Perl weekly challenge 385
2 # Task 2: Outermost Parentheses
3 #
4 # See https://wlmb.github.io/2026/08/03/PWC385/#task-2-outermost-parentheses
5 use v5.36;
6 use Text::Balanced qw(extract_bracketed);
7 die <<~"FIN" unless @ARGV;
8 Usage: $0 S0 S1...
9 to extract the string Sn after removing the
10 outermost parentheses of every primitive string in the
11 primitive decomposition of the given string.
12 FIN
13 for(@ARGV){
14 my $remaining=$_;
15 my ($extracted, $before);
16 my $out="";
17 while(1){
18 ($extracted, $remaining, $before)=extract_bracketed($remaining,"()", "[^\(]*");
19 if(!defined $extracted){
20 $out.="(", next if $remaining=~s/^\(//; #skip opening parenthesis and try again
21 $out.=$remaining;
22 last;
23 }
24 $extracted=~s/^\(|\)$//g;
25 $out.="$before$extracted";
26 }
27 say "'$_' -> \"$out\"";
28 }
29
Examples:
./ch-2.pl "()()()" "(((())))" "(()())(())" "()((()))()" "(()(()))(()())"
Results:
'()()()' -> ""
'(((())))' -> "((()))"
'(()())(())' -> "()()()"
'()((()))()' -> "(())"
'(()(()))(()())' -> "()(())()()"
Unbalanced examples:
./ch-2.pl "())" "(()" "(()(())(())"
Results:
'())' -> ")"
'(()' -> "("
'(()(())(())' -> "(()()"
/;