| 07 August 2026 | Challenge 385 |
Outermost Uncommons
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")
Solution
The examples show that it does not matter weather a word appears multiple times in the same string or if it appears in both strings to be counted as “common”. This lead to three simple steps to solve the task:
- Split the strings into lists of words.
- Join the lists.
- Select the words that appear exactly once in the joined list.
Perl
A combination of split and
List::MoreUtils::singleton
does the job.
The input is not restricted to two strings. With any number of given strings, the result is the list of words that appear only once over all lists.
use strict;
use warnings;
use List::MoreUtils 'singleton';
sub uncommon_words {
singleton map split, @_;
}
See the full solution to task 1.
J
Almost the same in J.
uncommon_words =: _(adverb define)
NB. convert a string to list of boxed words
words =. ;:
NB. count the frequencies of unique items and
NB. restrict to single appearances
singles =. 1&=@(#/.~) # ~.
NB. split x and y into words,
NB. join the two lists and
NB. restrict to singly appearing words
[: : (singles @ , & words) f.
)
'apple banana apple' uncommon_words 'banana orange'
┌──────┐
│orange│
└──────┘
See the full solution.
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: "(()(()))" + "(()())"
Solution
Perl
The task can be solved with a single (global) search/replace operation.
There are two named capture groups:
BPmatches a balanced pair of parentheses. Any number of non-parenthesis characters and any number of balanced parenthesis pairs may be contained within the outer pair. This capture group is used recursively to identify balanced parentheses.NPpossessively matches any number of non-parenthesis characters
Then remove the first and last character from each matched substring.
use strict;
use warnings;
sub outermost_parentheses {
shift =~ s{
(?<BP>
\(
(?&NP)
(?:
(?&BP)
(?&NP)
)*
\)
)
(?(DEFINE)(?<NP>[^()]*+))
}{substr $&, 1, -1}grex;
}
See the full solution to task 2.
J
J comes with a set of verbs and adverbs to apply regular expressions on strings.
Here the adverb rxapply can be used just like Perl’s s///ger: globally match a pattern, apply a piece of code on the matched substrings but do not modify the input string.
Using the regex from the Perl solution..
require 'regex'
NB. - compile pattern
NB. - behead and curtail all matched substrings
outermost_parentheses =: (rxcomp 0 : 0) & (}:@}. rxapply)
(?x)
(?<BP>
\(
(?&NP)
(?:
(?&BP)
(?&NP)
)*
\)
) (?#)
(?(DEFINE)(?<NP>[^()]*+))
)
outermost_parentheses '(()(()))(()())'
()(())()()