Perl Weekly Challenge: Week 316

Challenge 1:

Circular

You are given a list of words.

Write a script to find out whether the last character of each word is the first character of the following word.

Example 1
Input: @list = ("perl", "loves", "scala")
Output: true
Example 2
Input: @list = ("love", "the", "programming")
Output: false
Example 3
Input: @list = ("java", "awk", "kotlin", "node.js")
Output: true

We start by setting up a variable to hold the result. Being incorrigible optimists, we make its' default value True.

my $circular = True;

Now, starting from the second element...

for 1 .. @list.end -> $i {

...we compare its' first character with the last character of the previous element using .substr(). If the two are not equal, we set $circular to False and stop processing.

    if @list[$i].substr(0, 1) ne @list[$i - 1].substr(*-1, 1) {
        $circular = False;
        last;
    }

If both are equal, we continue to the next pair of elements and so on until we reach the end of @list.

}

Wether we have completed the loop or bailed out of it early, we print the value of $circular.

say $circular;

(Full code on Github.)

The Perl version is exactly the same bar syntactic differences.

my $circular = true;

for my $i (1 .. scalar @list - 1) {
    if (substr($list[$i], 0, 1) ne substr($list[$i - 1], -1, 1)) {
        $circular = false;
        last;
    }
}

Although Perl has true and false literals now, annoyingly they have no printable form atleast in version 5.38. So we need to do it ourselves.

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

(Full code on Github.)

Challenge 2:

Subsequence

You are given two string.

Write a script to find out if one string is a subsequence of another.

A subsequence of a string is a new string that is formed from the original string
by deleting some (can be none)  of the characters without disturbing the relative
positions of the remaining characters.
Example 1
Input: $str1 = "uvw", $str2 = "bcudvew"
Output: true
Example 2
Input: $str1 = "aec", $str2 = "abcde"
Output: false
Example 3
Input: $str1 = "sip", $str2 = "javascript"
Output: true

There is probably a more elegant way to do this, but the solution I came up with does the trick. What I do is to split $str1 into individual characters and after placing .* (regexese for match 0 or more characters of any type) between them join them up into one string again.

my $match = $str1.comb.join(q{.*});

This ia used as a regular expression to ,match() $str2. The success or failure of the match is converted to a Boolean value with .so and printed out with say().

say $str2.match(/<$match>/).so;

(Full code on Github.)

The Perl version works the same way except, once again, we have to print true and false values ourselves.

my $match = join q{.*}, split //, $str1;
say $str2 =~ /$match/x ? 'true' : 'false';

(Full code on Github.)