Perl Weekly Challenge 266: Uncommon Words

These are some answers to the Week 266, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on April 28, 2024 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 1: Uncommon Words

You are given two sentences, $line1 and $line2.

Write a script to find all uncommon words in any order in the given two sentences. Return ('') if none found.

A word is uncommon if it appears exactly once in one of the sentences and doesn’t appear in other sentence.

Example 1

Input: $line1 = 'Mango is sweet'
       $line2 = 'Mango is sour'
Output: ('sweet', 'sour')

Example 2

Input: $line1 = 'Mango Mango'
       $line2 = 'Orange'
Output: ('Orange')

Example 3

Input: $line1 = 'Mango is Mango'
       $line2 = 'Orange is Orange'
Output: ('')

We're given two sentences, but the words of these sentences can be processed as one merged collection of words: we only need to find words that appear once in the overall collection.

Uncommon Words in Raku

We use the words method to split the sentences into individual words. Then, in the light of the comment above, we merge the two word lists into a single Bag, using the (+) or Baggy addition operator,infix%E2%8A%8E). Finally, we select words that appear only once in the resulting Bag.

sub uncommon ($in1, $in2) {
    my $out = $in1.words ⊎ $in2.words; # Baggy addition 
    return grep {$out{$_} == 1}, $out.keys;
}

my @tests = ('Mango is sweet', 'Mango is sour'),
            ('Mango Mango', 'Orange'),
            ('Mango is Mango', 'Orange is Orange');
for @tests -> @test {
    printf "%-18s - %-18s => ", @test[0], @test[1];
    say uncommon @test[0], @test[1];
}

This program displays the following output:

$ raku ./uncommon.raku
Mango is sweet     - Mango is sour      => (sour sweet)
Mango Mango        - Orange             => (Orange)
Mango is Mango     - Orange is Orange   => ()

Uncommon Words in Perl

This is a port to Perl of the above Raku program. We use a hash instead of a Bag to store the histogram of words.

use strict;
use warnings;
use feature 'say';

sub uncommon {
    my %histo;
    $histo{$_}++ for map { split /\s+/ } @_;
    my @result = grep {$histo{$_} == 1} keys %histo;
    return @result ? join " ", @result : "''";
}

my @tests = ( ['Mango is sweet', 'Mango is sour'],
              ['Mango Mango', 'Orange'],
              ['Mango is Mango', 'Orange is Orange'] ); 
for my $test (@tests) {
    printf "%-18s - %-18s => ", $test->[0], $test->[1];
    say uncommon $test->[0], $test->[1];
}

This program displays the following output:

$ perl ./uncommon.pl
Mango is sweet     - Mango is sour      => sour sweet
Mango Mango        - Orange             => Orange
Mango is Mango     - Orange is Orange   => ''

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on May 5, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.