Perl Weekly Challenge 220: Common Characters
These are some answers to the Week 220, 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 June 11, 2023 at 23:59). This blog post offers some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.
Common Characters
You are given a list of words.
Write a script to return the list of common characters (sorted alphabetically) found in every word of the given list.
Example 1
Input: @words = ("Perl", "Rust", "Raku")
Output: ("r")
Example 2
Input: @words = ("love", "live", "leave")
Output: ("e", "l", "v")
Common Characters in Raku
Raku provides operators to make this task very simple. Each word is split into a list of individual letters and then, we use the infix ∩
set intersection operator,infix%E2%88%AA) to find the common characters. Note that we use the ∩
intersection operator together with the []
reduction meta-operator, which makes it possible to apply the intersection operator to any number of input lists.
sub common-char (@in) {
return sort keys ([∩] map {.lc.comb}, @in);
}
for <Perl Rust Raku>, <love live leave> -> @test {
printf "%-15s => ", "@test[]";
say common-char @test;
}
This program displays the following output:
$ raku ./common-characters.raku
Perl Rust Raku => (r)
love live leave => (e l v)
This program is simple enough to boil down to a Raku one-liner:
$ raku -e 'say sort keys ([∩] map {.lc.comb}, @*ARGS)' love live leave
(e l v)
Common Characters in Perl
Perl doesn't have sets or set operators, so we use hashes instead. For each list of characters, we first remove any duplicate letters (using the %unique
hash and then populate the %histo
histogram hash. At the end, we keep any letter whose count is equal to the number of words in the initial input list.
use strict;
use warnings;
use feature 'say';
sub common_char {
my %histo;
my @in = map lc $_, @_;
for my $word (@in) {
my %unique = map { $_ => 1 } split //, $word;
$histo{$_}++ for keys %unique;
}
return sort grep { $histo{$_} == scalar @in } keys %histo;
}
for my $test ([<Perl Rust Raku>], [<love live leave>]) {
printf "%-15s => ", "@$test";
say join " ", common_char @$test;
}
This program displays the following output:
$ perl ./common-characters.pl
Perl Rust Raku => r
love live leave => e l v
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 June 18, 2023. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment