This is my response to The Weekly Challenge #375.
Input: @array1 = ("apple", "banana", "cherry")
@array2 = ("banana", "cherry", "date")
Output: 2
Example 2:
Input: @array1 = ("a", "ab", "abc")
@array2 = ("a", "a", "ab", "abc")
Output: 2
"a" appears once in @array1 but appears twice in @array2, therefore, not counted.
Example 3:
Input: @array1 = ("orange", "lemon")
@array2 = ("grape", "melon")
Output: 0
Example 4:
Input: @array1 = ("test", "test", "demo")
@array2 = ("test", "demo", "demo")
Output: 0
Example 5:
Input: @array1 = ("Hello", "world")
@array2 = ("hello", "world")
Output: 1
String comparison is case sensitive.
#! /usr/bin/env raku
unit sub MAIN ($array1, $array2, :v(:$verbose));
my @array1 = $array1.words;
my @array2 = $array2.words;
my @unique1 = @array1.Bag.grep( *.value == 1 )>>.key;
my @unique2 = @array2.Bag.grep( *.value == 1 )>>.key;
my @common = @unique1 (&) @unique2;
if $verbose
{
say ": Array1: @array1[]";
say ": Array2: @array2[]";
say ": Unique1: @unique1[]";
say ": Unique2: @unique2[]";
say ": Common: { @common>>.key }";
}
say @common.elems;
[3] The two arrays, each one as a space separated string.
[5+6] Extract the words with words, thus
giving us the two arrays in this roundabout way.
See docs.raku.org/routine/words for more information about words.
[8+9] Get the values that appear exactly once from the
array. We do this with Bag, a hash like structure keeping
track of the occurences. Then we grep out (i.e. keep) only
those that occure once. The result of this is a list of pair
objects, so we pick the key (i.e. the word) from each pair with
>>.key.
See docs.raku.org/routine/Bag for more information about Bag.
[13] Get the intersection of the two lists, (i.e.
elements occuring in both) using the intersection operator
(&).
See
docs.raku.org/routine/(&),%20infix%20%E2%88%A9
for more information about the intersection operator (&).
[22] Print the number of common elements.
Running it:
$ ./single-common-word "apple banana cherry" "banana cherry date"
2
$ ./single-common-word "a ab abc" "a a ab abc"
2
$ ./single-common-word "orange lemon" "grape melon"
0
$ ./single-common-word "test test demo" "test demo demo"
0
$ ./single-common-word "Hello world" "hello world"
1
Looking good.
With verbose mode:
$ ./single-common-word -v "apple banana cherry" "banana cherry date"
: Array1: apple banana cherry
: Array2: banana cherry date
: Unique1: banana apple cherry
: Unique2: date cherry banana
: Common: banana cherry
2
$ ./single-common-word -v "a ab abc" "a a ab abc"
: Array1: a ab abc
: Array2: a a ab abc
: Unique1: abc ab a
: Unique2: abc ab
: Common: abc ab
2
$ ./single-common-word -v "orange lemon" "grape melon"
: Array1: orange lemon
: Array2: grape melon
: Unique1: orange lemon
: Unique2: melon grape
: Common:
0
$ ./single-common-word -v "test test demo" "test demo demo"
: Array1: test test demo
: Array2: test demo demo
: Unique1: demo
: Unique2: test
: Common:
0
$ ./single-common-word -v "Hello world" "hello world"
: Array1: Hello world
: Array2: hello world
: Unique1: world Hello
: Unique2: world hello
: Common: world
1
Input: $num = 240, $k = 2
Output: 2
Substring with length 2:
24: 240 is divisible by 24
40: 240 is divisible by 40
Example 2:
Input: $num = 1020, $k = 2
Output: 3
Substring with length 2:
10: 240 is divisible by 10
02: 240 is divisible by 2
20: 240 is divisible by 20
Example 3:
Input: $num = 444, $k = 2
Output: 0
Substring with length 2:
First "44": 444 is not divisible by 44
Second "44": 444 is not divisible by 44
Example 4:
Input: $num = 17, $k = 2
Output: 1
Substring with length 2:
17: 17 is divisible by 17
Example 5:
Input: $num = 123, $k = 1
Output: 2
Substring with length 1:
1: 123 is divisible by 1
2: 123 is not divisible by 2
3: 123 is divisible by 3
#! /usr/bin/env raku
unit sub MAIN (UInt $num,
UInt $k where $k > 0 && $k <= min($num.chars, 9),
:v(:$verbose));
my $matches = 0;
for 0 .. $num.chars - $k -> $start
{
my $candidate = $num.substr($start, $k);
my $match = $num %% $candidate;
$matches++ if $match;
say ": candidate $candidate [start:$start stop:{ \
$start + $k -1 }] { $match ?? "- $num is divisible \
by { $candidate.Int }" !! ""}" if $verbose;
}
say $matches;
[3] An unsigned integer (i.e. zero is allowed).
[4] Another unsigned integer, but this one must have a value between 1 and "the length of the first one or 9", whichever is smallest.
[7] The number of matches, initially zero.
[9] Iterate over all the possible start positions, allowing for the
substring (with length $k) to fit inside the rest of $num.
[11] Use substr to extract the substring.
See docs.raku.org/routine/substr for more information about substr.
[12] Do we have a match?
[14] If so, count it.
[21] Print the result (number of matches).
Running it:
$ ./find-k-beauty 240 2
2
$ ./find-k-beauty 1020 2
3
$ ./find-k-beauty 444 2
0
$ ./find-k-beauty 17 2
1
$ ./find-k-beauty 123 1
2
Looking good.
With verbose mode:
$ ./find-k-beauty -v 240 2
: candidate 24 [start:0 stop:1] - 240 is divisible by 24
: candidate 40 [start:1 stop:2] - 240 is divisible by 40
2
$ ./find-k-beauty -v 1020 2
: candidate 10 [start:0 stop:1] - 1020 is divisible by 10
: candidate 02 [start:1 stop:2] - 1020 is divisible by 2
: candidate 20 [start:2 stop:3] - 1020 is divisible by 20
3
$ ./find-k-beauty -v 444 2
: candidate 44 [start:0 stop:1]
: candidate 44 [start:1 stop:2]
0
$ ./find-k-beauty -v 17 2
: candidate 17 [start:0 stop:1] - 17 is divisible by 17
1
$ ./find-k-beauty -v 123 1
: candidate 1 [start:0 stop:0] - 123 is divisible by 1
: candidate 2 [start:1 stop:1]
: candidate 3 [start:2 stop:2] - 123 is divisible by 3
2
And that's it.