Perl Weekly Challenge: Week 317

Challenge 1:

Acronyms

You are given an array of words and a word.

Write a script to return true if concatenating the first letter of each word in the given array matches the given word, return false otherwise.

Example 1
Input: @array = ("Perl", "Weekly", "Challenge")
    $word  = "PWC"
Output: true
Example 2
Input: @array = ("Bob", "Charlie", "Joe")
    $word  = "BCJ"
Output: true
Example 3
Input: @array = ("Morning", "Good")
    $word  = "MM"
Output: false

We can solve this with a one liner. We take the first command-line argument with .shift() and compare it to the rest which have their first characters taken with .substr() and .map() and .join()ed together into one string. This comparison is converted explicity into a Boolean value with .so and this is printed out with .say().

(@*ARGS.shift eq @*ARGS.map({$_.substr(0,1)}).join).so.say

(Full code on Github.)

The Perl version is slightly longer because we have to explicitly print the words 'true' and 'false'.

say shift eq (join q{}, map{ substr $_, 0, 1} @ARGV) ? "true" : "false"

(Full code on Github.)

Challenge 2:

Friendly Strings

You are given two strings.

Write a script to return true if swapping any two letters in one string match the other string, return false otherwise.

Example 1
Input: $str1 = "desc", $str2 = "dsec"
Output: true
Example 2
Input: $str1 = "fuck", $str2 = "fcuk"
Output: true
Example 3
Input: $str1 = "poo", $str2 = "eop"
Output: false
Example 4
Input: $str1 = "stripe", $str2 = "sprite"
Output: true

First we split up $str1 into individual characters.

my @chars = $str1.comb;

We also need to store the result. Initially, it is set to False.

my $result = False;

Now for every combination of 2 indices in `@chars)...

for @chars.keys.combinations(2) -> ($i, $j) {

...we make a temporary copy of @chars...

    my @temp = @chars;

and swap the elements in the copy at those indices.

    (@temp[$i], @temp[$j]) = (@temp[$j], @temp[$i]);

The copy is join()ed up into a string and compared to $str2. If they are equal we have success. $result is set to True and processing is stopped.

    if @temp.join eq $str2 {
        $result = True;
        last;
    }

If they are not equal we redo the loop with the next combination.

}

If we have exhausted all combinations without a suceessful match, $result is still False. Whatever its' value, we print it out.

say $result;

(Full code on Github.)

This is the Perl version.

my @chars = split //, $str1;
my $result = false;

We don't have .combinations() so as a workaround we use a double-for loop. This also requires knowing the length of $str1.

my $length = length $str1;

for my $i (0 .. $length - 1) {
    for my $j (($i + 1) .. $length - 1) {
        my @temp = @chars;

        ($temp[$i], $temp[$j]) = ($temp[$j], $temp[$i]);

        if ((join q{}, @temp) eq $str2) {
            $result = true;
            last;
        }
    }
}

say $result ? 'true' : 'false';

(Full code on Github.)