This is my response to The Weekly Challenge #319.
Input: @list = ("unicode", "xml", "raku", "perl")
Output: 2
The words are "unicode" and "raku".
Example 2:
Input: @list = ("the", "weekly", "challenge")
Output: 2
Example 3:
Input: @list = ("perl", "python", "postgres")
Output: 0
#! /usr/bin/env raku
subset VOWEL where * ~~ /<[aeiouyAEIOUY]>/; # [1]
unit sub MAIN (*@list where @list.elems > 1 # [2]
&& all(@list) ~~ /^<[a..z A..Z]>+$/, # [3]
:v(:$verbose));
my @matches = @list.grep({ .substr(0,1) ~~ VOWEL || # [4]
.substr(.chars -1,1) ~~ VOWEL}); # [4a]
say ": Matching words: @matches[]" if $verbose;
say @matches.elems ?? @matches.elems !! -1; # [5]
[1] A custom type, set up with subset
, to match a single
vowel. Note that examples does not include uppercase letters, but I have chosen
to support them as well.
See docs.raku.org/language/typesystem#subset for more information about subset
.
[2] A list of words, with at least 2.
[3] Ensure that the words contain alphabetic characters only, with at least one character each.
[4] Keep the words starting or ending [4a] with a vowel.
Note that this will also match a word both starting and ending with a vowel. This may or may not be ok. The examples does not help out here.
[5] Print the number of matching words, or -1
if none.
Running it:
$ ./word-count unicode xml raku perl
2
$ ./word-count the weekly challenge
3
$ ./word-count perl python postgress
-1
Looking good.
With verbose mode:
$ ./word-count -v unicode xml raku perl
Matching words: unicode raku
2
$ ./word-count -v the weekly challenge
: Matching words: the weekly challenge
3
$ ./word-count -v perl python postgress
: Matching words:
-1
Input: @array_1 = (1, 2, 3, 4)
@array_2 = (3, 4, 5, 6)
Output: 3
The common integer in both arrays: 3, 4
The minimum is 3.
Example 2:
Input: @array_1 = (1, 2, 3)
@array_2 = (2, 4)
Output: 2
Example 3:
Input: @array_1 = (1, 2, 3, 4)
@array_2 = (5, 6, 7, 8)
Output: -1
#! /usr/bin/env raku
unit sub MAIN ($array_1, $array_2, :v(:$verbose)); # [1]
my @array_1 = $array_1.words; # [2]
my @array_2 = $array_2.words; # [2a]
die "Array1: Non-negative integers only" # [3]
unless all(@array_1) ~~ /^<[0..9]>+$/;
die "Array2: Non-negative integers only" # [3]
unless all(@array_2) ~~ /^<[0..9]>+$/;
my @common = @array_1 (&) @array_2; # [4]
say ": Common: { @common>>.key.sort.join(",")}" if $verbose;
say @common ?? @common>>.key.sort.first !! -1; # [5]
[1] The two arrays as space separated strings.
[2] Turn the space separated strings into arrays with words
.
See docs.raku.org/routine/words for more information about words
.
[3] The usage of -1
as a «not found» value indicates that we should not
allow negative values in the input. Zeroes in the input is ok, as that would
otherwise have been a legal «not found» value.
[4] Use the intersection operator (&)
to get the
intersection of the two arrays; i.e. the common elements.
See
docs.raku.org/routine/(&),%20infix%20%E2%88%A9
for more information about the intersection operator (&)
.
[5] Print the lowest value (with first
on the
sorted keys), or -1
if the intersection is empty.
See docs.raku.org/routine/first for more information about first
.
Running it:
$ ./minimum-common "1 2 3 4" "3 4 5 6"
3
$ ./minimum-common "1 2 3" "2 4"
2
$ ./minimum-common "1 2 3 4" "5 6 7 8"
-1
Looking good.
With verbose mode:
$ ./minimum-common -v "1 2 3 4" "3 4 5 6"
: Common: 3,4
3
$ ./minimum-common -v "1 2 3" "2 4"
: Common: 2
2
$ ./minimum-common -v "1 2 3 4" "5 6 7 8"
: Common:
-1
And that's it.