### Perl Weekly Challenge: Week 256

#### Challenge 1:

Maximum Pairs

You are given an array of distinct words, `@words`.

Write a script to find the maximum pairs in the given array. The words `\$words[i]` and `\$words[j]` can be a pair one is reverse of the other.

##### Example 1
``````Input: @words = ("ab", "de", "ed", "bc")
Output: 1

There is one pair in the given array: "de" and "ed"
``````
##### Example 2
``````Input: @words = ("aa", "ba", "cd", "ed")
Output: 0
``````
##### Example 3
``````Input: @words = ("uv", "qp", "st", "vu", "mn", "pq")
Output: 2
``````

Rakus' `.combinations(2)` method as the name suggests gives all 2 element combinations of the command-line arguments. For each of these pairs, we filter out the ones where the first member is the same as the reversed second member with `.grep()`. They are counted with `.elems()` and the result is printed with `.say()`.

``````@*ARGS.combinations(2).grep({\$_[0] eq \$_[1].flip}).elems.say
``````

(Full code on Github.)

Perl needed a `combinations()` function which I took from previous challenges. With that, it was almost as succint as Raku.

``````say scalar grep { \$_->[0] eq reverse \$_->[1] } combinations(\@ARGV, 2);
``````

(Full code on Github.)

#### Challenge 2:

Most Frequent Word

You are given two strings, `\$str1` and `\$str2`.

Write a script to merge the given strings by adding in alternative order starting with the first string. If a string is longer than the other then append the remaining at the end.

##### Example 1
``````Input: \$str1 = "abcd", \$str2 = "1234"
Output: "a1b2c3d4"
``````
##### Example 2
``````Input: \$str1 = "abc", \$str2 = "12345"
Output: "a1b2c345"
``````
##### Example 3
``````Input: \$str1 = "abcde", \$str2 = "123"
Output: "a1b2c3de"
``````

I was hoping this could be a very short Raku one-liner. This is what I tried:

``````(\$str1.comb Z~ \$str2.comb).join.say;
``````

`.comb()` splits each of the input strings into arrays of characters. The `Z` operator consecutively makes pairs, one from each array. In combination with the `~` operator, the pairs are joined into two-character strings. `.join()` joins all these little strings into one big one and finally, `.say()` prints it out.

Alas this only works for example 1. The problem is if the two arrays are of different lengths, `Z~` will stop processing after the shorter one ends. Which makes sense; at that point there is nothing for the elements of the longer list to pair with. But this is no good for our problem. So I had to add extra code.

This variable will hold the part of the longer string which is beyond the length of the shorter string.

``````my \$remainder = '';
``````

If the length of `\$str1` is less than the length of `\$str2`...

``````if \$str1.chars < \$str2.chars {
``````

... the remainder becomes the extra characters of `\$str2` beyond the length of `\$str1`, removed from `\$str2` with `.splice()`. Because `.splice()` is a method of the `Array` class, `\$str2` has to be converted with `.comb()` and `.Array()` first and then joined back up into a string.

``````    \$remainder = \$str2.comb.Array.splice(\$str1.chars, *).join;
``````

If the length of `\$str1` is greater than the length of `\$str2`, the same process occurs except the extra characters of `\$str1` are removed to form the `\$remainder`.

``````} elsif \$str1.chars > \$str2.chars {
\$remainder = \$str1.comb.Array.splice(\$str2.chars, *).join;
}
``````

If both strings are the same length, nothing more needs to be done and `\$remainder` can remain empty.

At this point, `\$str1` and `\$str2` should both be of the same length with a possible remainder. Now we can rewrite our original line of code to perform the `Z~` operation and append the remainder.

``````say (\$str1.comb Z~ \$str2.comb).join ~ \$remainder;
``````

(Full code on Github.)

For Perl, we need a replacement for `Z~`. I had already written one for challenge 138 but I took the opportunity to extend it beyond being just a Raku clone.

This function combines the splitting etc. functionality of my Raku solution with `Z~`.

``````sub Ztilde {
my @a = split //, \$_[0];
my @b = split //, \$_[1];

my \$remainder = q{};

if (scalar @a < scalar @b) {
\$remainder = join q{}, splice @b, scalar @a;
} elsif (scalar @a > scalar @b) {
\$remainder = join q{}, splice @a, scalar @b;
}

my @result;
for my \$i (0 .. scalar @b - 1) {
push @result, \$a[\$i], \$b[\$i];
}
push @result, \$remainder;

return join q{}, @result;
}
``````

As a result the main code in my Perl version only is this:

``````say Ztilde(\$str1, \$str2);
``````

(Full code on Github.)