The Bear's Den

Enter at your own risk

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:

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.
)

Example 1:

   '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:

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>[^()]*+))
)

Example 5

   outermost_parentheses '(()(()))(()())'
()(())()()