This is my response to The Weekly Challenge #239.
Input: @arr1 = ("ab", "c")
@arr2 = ("a", "bc")
Output: true
Using @arr1, word1 => "ab" . "c" => "abc"
Using @arr2, word2 => "a" . "bc" => "abc"
Example 2:
Input: @arr1 = ("ab", "c")
@arr2 = ("a", "bc")
Output: true
Using @arr1, word1 => "ab" . "c" => "abc"
Using @arr2, word2 => "a" . "bc" => "abc"
Example 3:
Input: @arr1 = ("ab", "c")
@arr2 = ("ac", "b")
Output: false
Using @arr1, word1 => "ab" . "c" => "abc"
Using @arr2, word2 => "ac" . "b" => "acb"
This is easy, if we assume that the order of the array elements matter - as inferred by the examples.
#! /usr/bin/env raku
unit sub MAIN ($arr1, $arr2); # [1]
say $arr1.words.join eq $arr2.words.join # [2]
?? 'true' # [2a]
!! 'false'; # [2b]
[1] Two input strings, with space as the separator between the array elements.
[2] Get the array elements (with words
), glue them together
(without the spaces, with join
) and compare the two resulting
strings. Print 'true' if they are equal [2a], and 'false' [2b] if not.
Running it:
$ ./same-string "ab c" "a bc"
true
$ ./same-string "ab c" "ac b"
false
$ ./same-string "ab cd e" "abcde"
true
It is easyish to support random order:
File: same-string-shuffle
#! /usr/bin/env raku
unit sub MAIN ($arr1, $arr2);
for $arr1.words.permutations>>.join.unique -> $first # [1]
{
for $arr2.words.permutations>>.join.unique -> $second # [2]
{
if $first eq $second # [3]
{
say 'true'; # [3a]
exit; # [3b]
}
}
}
say 'false'; # [4]
[1] Split the first string into words, generate all the possible
permutations (shuffled lists), and join each one into a single string.
Remove duplicates (*), if any (with unique
). Iterate over
them.
[2] Ditto, for the second string.
[3] Equal? If so, say so [3a] and exit [3b].
[4] We have looked through all the permutations without finding a match. Then we have failed. Say so.
[*] Duplicates occur if we have duplicate values in the input array. E.g.
"a", "a", "b"
.
Running it gives the expected result:
$ ./same-string-shuffle "ab c" "a bc"
true
$ ./same-string-shuffle "ab c" "ac b"
false
$ ./same-string-shuffle "ab cd e" "abcde"
true
Let us show off random order:
$ ./same-string-shuffle "c e ab d" "abcde"
true
$ ./same-string-shuffle "ce ab d" "abcde"
false
Missing verbose mode?
It is easy to add, but the duplicate removal (unique
in
[1] and [2]) had to go.
#! /usr/bin/env raku
unit sub MAIN ($arr1, $arr2, :v(:$verbose));
for $arr1.words.permutations -> @first # [1]
{
for $arr2.words.permutations -> @second # [1a]
{
if @first.join eq @second.join # [1b]
{
say ": { @first.map({ "\"$_\"" }).join(" ") } === \
{ @second.map({ "\"$_\"" }).join(" ") }" if $verbose;
say 'true';
exit;
}
elsif $verbose
{
say ": { @first.map({ "\"$_\"" }).join(" ") } =!= \
{ @second.map({ "\"$_\"" }).join(" ") }";
}
}
}
say 'false';
[1] We have arrays this time in the two loops, so we must join them together (in [1b]) before we can compare the strings.
Running it:
$ ./same-string-verbose -v "ab c" "a bc"
: "ab" "c" === "a" "bc"
true
$ ./same-string-verbose -v "c e ab d" "abcde"
: "c" "e" "ab" "d" =!= "abcde"
: "c" "e" "d" "ab" =!= "abcde"
: "c" "ab" "e" "d" =!= "abcde"
: "c" "ab" "d" "e" =!= "abcde"
: "c" "d" "e" "ab" =!= "abcde"
: "c" "d" "ab" "e" =!= "abcde"
: "e" "c" "ab" "d" =!= "abcde"
: "e" "c" "d" "ab" =!= "abcde"
: "e" "ab" "c" "d" =!= "abcde"
: "e" "ab" "d" "c" =!= "abcde"
: "e" "d" "c" "ab" =!= "abcde"
: "e" "d" "ab" "c" =!= "abcde"
: "ab" "c" "e" "d" =!= "abcde"
: "ab" "c" "d" "e" === "abcde"
true
$ ./same-string-verbose -v "ce ab d" "abcde"
: "ce" "ab" "d" =!= "abcde"
: "ce" "d" "ab" =!= "abcde"
: "ab" "ce" "d" =!= "abcde"
: "ab" "d" "ce" =!= "abcde"
: "d" "ce" "ab" =!= "abcde"
: "d" "ab" "ce" =!= "abcde"
false
Input: @str = ("ad", "bd", "aaab", "baa", "badab")
$allowed = "ab"
Output: 2
Strings "aaab" and "baa" are consistent since they only contain characters 'a' and 'b'.
Example 2:
Input: @str = ("a", "b", "c", "ab", "ac", "bc", "abc")
$allowed = "abc"
Output: 7
Example 3:
Input: @str = ("cc", "acd", "b", "ba", "bac", "bad", "ac", "d")
$allowed = "cad"
Output: 4
Strings "cc", "acd", "ac", and "d" are consistent.
#! /usr/bin/env raku
unit sub MAIN ($allowed, *@str where @str.elems > 0); # [1]
my @allow-canonical = $allowed.comb; # [2]
my $consistent = 0; # [3]
for @str -> $str # [4]
{
$consistent++ if $str.comb.unique (<=) @allow-canonical; # [5]
}
say $consistent; # [6]
[1] The allowed characters as the first argument, followed by the strings.
[2] A list of allowed characters.
[3] The final count will end up here.
[4] Iterate over the strings.
[5] Increse the counter if the characters in the string is
a subset (or equal) (the (<=)
operator) to the allowed characters.
See
docs.raku.org/language/operators infix (<=)
for more information about the subset or equal to operator (<=)
.
[6] Print the result.
Running it:
$ ./consistent-string ab ad bd aaab baa badab
2
$ ./consistent-string abc a b c ab ac bc abc
7
$ ./consistent-string cad cc acd b ba bac bad ac d
4
Looking good.
Missing verbose mode? Let us remedy that.
File: consistent-string-verbose
#! /usr/bin/env raku
unit sub MAIN ($allowed, *@str where @str.elems > 0, :v(:$verbose));
my @allow-canonical = $allowed.comb;
my $consistent = 0;
for @str -> $str
{
my @str-canonical = $str.comb.unique;
if @str-canonical (<=) @allow-canonical
{
$consistent++;
say ": + $str - consistent" if $verbose;
}
elsif $verbose
{
say ": - $str" if $verbose;
}
}
say $consistent;
Running it:
$ ./consistent-string-verbose -v ab ad bd aaab baa badab
: - ad
: - bd
: + aaab - consistent
: + baa - consistent
: - badab
2
$ ./consistent-string-verbose -v abc a b c ab ac bc abc
: + a - consistent
: + b - consistent
: + c - consistent
: + ab - consistent
: + ac - consistent
: + bc - consistent
: + abc - consistent
7
$ ./consistent-string-verbose -v cad cc acd b ba bac bad ac d
: + cc - consistent
: + acd - consistent
: - b
: - ba
: - bac
: - bad
: + ac - consistent
: + d - consistent
4
And that's it.