Perl Weekly Challenge 96
I admittedly took a shortcut for part two this week, but it allowed me to introduce modules here (I don’t believe I have used them before in a blog), so I think it makes up for it. 🙂
Task 1: Reverse Words
You are given a string $S
.
Write a script to reverse the order of words in the given string. The string may contain leading/trailing spaces. The string may have more than one space between words in the string. Print the result without leading/trailing spaces and there should be only one space between words.
Example 1
Input: $S = "The Weekly Challenge"
Output: "Challenge Weekly The"
Example 2
Input: $S = " Perl and Raku are part of the same family "
Output: "family same the of part are Raku and Perl"
Solution
See below for explanation and any implementation-specific comments.
sub challenge(Str $S) returns Str {
$S.trim.words.reverse.join(' ');
}
sub MAIN(Str $S) {
say challenge($S);
}
This program runs as such:
$ raku ch-1.raku 'The Weekly Challenge'
Challenge Weekly The
Explanation
Pretty easy one-liner here. Here is the logic:
- Take the string and
trim
whitespace off of the beginning and the end. - Split it into individual words using the handy
words
method (the equivalent ofsplit(/<space>+/)
). - Reverse the list generated from Step 2
- Re-join the list into a space-separated string using
.join(' ')
.
Task 2: Edit Distance
You are given two strings $S1
and $S2
.
Write a script to find out the minimum operations required to convert $S1
into $S2
. The operations can be “insert,” “remove,” or “replace” a character. Check out Wikipedia page for more information.
Example 1
Input: $S1 = "kitten"; $S2 = "sitting"
Output: 3
Explanation:
Operation 1: replace 'k' with 's'
Operation 2: replace 'e' with 'i'
Operation 3: insert 'g' at the end
Example 2
Input: $S1 = "sunday"; $S2 = "monday"
Output: 2
Explanation:
Operation 1: replace 's' with 'm'
Operation 2: replace 'u' with 'o'
Solution
See below for explanation and any implementation-specific comments.
use Text::Levenshtein; # imports `distance` # [1]
sub challenge(Str $S1, Str $S2) returns Int {
distance($S1.lc, $S2.lc).head; # [2][3]
}
sub MAIN(Str $S1, Str $S2) {
say challenge($S1, $S2);
}
This program runs as such:
$ raku ch-2.raku kitten sitting
3
Explanation
This was definitely a cop-out. Edit distance is also known as Levenshtein Distance; when an algorithm has someone’s name attached to it, it is usually better to find an existing implementation. 😅 With that being said, if anyone is interested in the Raku implementation of the algorithm, here is the source code for Text::Levenshtein
.
In case it is not obvious, we simply pass the input strings to distance
and let it do the work.
Specific Comments
- I encourage anyone reading this to read the Raku documentation on modules. Basically,
use
is one of several keywords to import modules, and is probably the most common you will see in the wild. You can import specific elements, if the author allows it, or you can write it as we did here and get the default imports. distance
will treat uppercase and lowercase letters differently, which I did not want, so we explicitly cast everything to lowercase (.lc
) before passing them todistance
.distance
will accept a variable number of arguments and compare the 2nd to Nth arguments to the first one, returning an array of Levenshtein distances. Since we only have two arguments, we need to extract the first (and only) distance in the array usinghead
.
Final Thoughts
In my day-to-day I always encourage folks to use modules where possible. In puzzles like these, I usually prefer to write my own implementation, even if it is less efficient. But it was a long week, so I took the lazy way out. 😉 See y’all next week!