ETOOBUSY 🚀 minimal blogging for the impatient
PWC083 - Words Length
TL;DR
Here we are with TASK #1 from the Perl Weekly Challenge #083. Enjoy!
The challenge
You are given a string $S with 3 or more words. Write a script to find the length of the string except the first and last words ignoring whitespace.
The questions
Well, the first question is what’s a word? Can we consider it as any sequence of non-spacing characters? This is what we will assume from now on, anyway.
Next is… is the string allowed to start with empty spaces, or end with them? Or is it always trimmed?
An aside question out of curiosity: why do we get rid of the first and last words?!?
The solution
There are many ways to do this that come to mind, let’s pick one:
sub words_length ($text) {
length($text =~ s{\A \s* \S+ | \s+ | \S+ \s* \z}{}grmxs);
}
A little cryptic, uh?
The idea is to take the input string $text
and get rid of everything
that should not participate into the counting, using the substitution
operator s. So we can get rid of the first word like this:
$text ~= s{\A \s* \S+}{}mxs;
i.e. by attaching to the beginning of $text
(\A
), removing the
optional initial whitespace and then as many non-spacing characters as
possible.
Similarly, we can proceed with the last word:
$text =~ s{\S+ \s* \z}{}mxs;
Last, we can get rid of all spaces:
$text =~ s{\s+}{}gmxs;
Note that we’re including the /g
modifier here, because we want to
remove all of them, not only the first batch we encounter.
It turns out that we can combine all of them, thanks again to the /g
modifier… so there we go, the initial solution!
As a final touch, we’re using the /r
modifier, which makes sure to
leave the original string untouched and return a modified copy instead.
So at this point, the only thing left is to count the number of
characters with length
.
The full code, should you want to try that out:
#!/usr/bin/env perl
use 5.024;
use warnings;
use experimental qw< postderef signatures >;
no warnings qw< experimental::postderef experimental::signatures >;
say words_length(shift || 'The Weekly Challenge');
sub words_length ($text) {
length($text =~ s{\A \s* \S+ | \s+ | \S+ \s* \z}{}grmxs);
}