Common Count
with Raku

by Arne Sommer

Common Count with Raku

[341] Published 4. May 2025.

This is my response to The Weekly Challenge #319.

Challenge #319.1: Word Count

You are given a list of words containing alphabetic characters only.

Write a script to return the count of words either starting with a vowel or ending with a vowel.

Example 1:
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
File: word-count
#! /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

Challenge #319.2: Minimum Common

You are given two arrays of integers.

Write a script to return the minimum integer common to both arrays. If none found return -1.

Example 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
File: minimum-common
#! /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.