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