This is my response to The Weekly Challenge #385.
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")
#! /usr/bin/env raku
unit sub MAIN (*@args);
(@args[0].words, @args[1].words)
.Bag
.grep({ .value == 1 })
.map(*.key)
.sort
.say;
[3] Catch the arguments, whatever they may be.
I have sprinkled the original row 5 with a massive dose of newlines to make it easier to comment on each part.
[5] Split the first two arguments into words.
See docs.raku.org/routine/words for more information about words.
[6] Turn the two word lists into a Bag, a hash like
structure with a key count.
See docs.raku.org/type/Bag for more information about the Bag type.
[7] Keep words that only occur once.
[8] Use map to extract the key - the word - from the Pair
objects in the Bag.
[9] Sort the result,
[10] and print it.
Running it:
$ ./uncommon-words "apple banana apple" "banana orange"
(orange)
$ ./uncommon-words "cat dog" "bird fish"
(bird cat dog fish)
$ ./uncommon-words "the quick brown fox" "the quick"
(brown fox)
$ ./uncommon-words "hello" "hello"
()
$ ./uncommon-words "blue blue red" "red green green yellow"
(yellow)
Looking good.
No verbose mode on this one, as the onelinery format does not really accomodate it.
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: "(()(()))" + "(()())"
#! /usr/bin/env raku
unit sub MAIN ($str where $str ~~ /^ <[\(\)]>+ $/,
:v($verbose));
my @primitives = gather
{
my $depth = 0;
my $primitive = '';
for $str.comb -> $char {
$primitive ~= $char;
$char eq '(' ?? $depth++ !! $depth--;
die "Encountered ')' without a preciding '('" if $depth < 0;
if $depth == 0
{
take $primitive;
say ": Primitive: $primitive" if $verbose;
$primitive = '';
}
}
die "Missing ')'" if $depth > 0;
};
say @primitives.map({ .substr(1, .chars - 2) }).join;
[3] Ensure parenthesises only.
[6] Use gather/take to extract the primitive
strings.
See my Raku Gather, I Take article or docs.raku.org/language/control#gather/take for more information about gather/take.
[8] The depth, or parenthesis count.
[9] The current primitive string is a work in progress.
[11] Iterate over the characters in the input.
[12] Add it to the primitive string.
[13] Update the depth.
[15] Negative dept? That's an error.
[17] Zero depth? Then we have a primitive string.
[19] Return it (with take).
[21] Reset the primitive string, ready for the next iteration - if any.
[25] Positive dept when finished (with the input) is an error.
[28] Get rid of the first and last character (i.e. the outermost parentheses) in each string, before printinh them.
Running it:
$ ./ outermost-parentheses "()()()"
$ ./outermost-parentheses "(((())))"
((()))
$ ./outermost-parentheses "(()())(())"
()()()
$ ./outermost-parentheses "()((()))()"
(())
$ ./outermost-parentheses "(()(()))(()())"
()(())()()
Looking good.
With verbose mode:
$ ./outermost-parentheses -v "()()()"
: Primitive: ()
: Primitive: ()
: Primitive: ()
$ ./outermost-parentheses -v "(((())))"
: Primitive: (((())))
((()))
$ ./outermost-parentheses -v "(()())(())"
: Primitive: (()())
: Primitive: (())
()()()
$ ./outermost-parentheses -v "()((()))()"
: Primitive: ()
: Primitive: ((()))
: Primitive: ()
(())
$ ./outermost-parentheses -v "(()(()))(()())"
: Primitive: (()(()))
: Primitive: (()())
()(())()()
And that's it.