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;
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';
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;
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';