Perl Weekly Challenge: Week 360
Challenge 1:
Text Justifier
You are given a string and a width.
Write a script to return the string that centers the text within that width using asterisks * as padding.
Example 1
Input: $str = "Hi", $width = 5
Output: "*Hi**"
Text length = 2, Width = 5
Need 3 padding characters total
Left padding: 1 star, Right padding: 2 stars
Example 2
Input: $str = "Code", $width = 10
Output: "***Code***"
Text length = 4, Width = 10
Need 6 padding characters total
Left padding: 3 stars, Right padding: 3 stars
Example 3
Input: $str = "Hello", $width = 9
Output: "**Hello**"
Text length = 5, Width = 9
Need 4 padding characters total
Left padding: 2 stars, Right padding: 2 stars
Example 4
Input: $str = "Perl", $width = 4
Output: "Perl"
No padding needed
Example 5
Input: $str = "A", $width = 7
Output: "***A***"
Text length = 1, Width = 7
Need 6 padding characters total
Left padding: 3 stars, Right padding: 3 stars
Example 6
Input: $str = "", $width = 5
Output: "*****"
Text length = 0, Width = 5
Entire output is padding
I'm going to show the Perl solution first.
We create an output string as long as $width and fill it with asterisks.
my $output = '*' x $width;
Then we calculate an offset which is the $width minus the length of $str divided
by 2 and replace length of $str asterisks in $output with $str using substr().
substr $output, ($width - length $str) / 2, length $str, $str;
Finally, we print $output.
say $output;
I thought the Raku solution would work the same way and it mostly does except...
my $output = '*' x $width;
.substr() doesn't replace characters in immutable strings. You have to use the
.substr-rw() method to do that.
$output.substr-rw(($width - $str.chars) / 2, $str.chars) = $str;
say $output;
Challenge 2:
Word Sorter
You are give a sentence.
Write a script to order words in the given sentence alphabetically but keeps the words themselves unchanged.
Example 1
Input: $str = "The quick brown fox"
Output: "brown fox quick The"
Example 2
Input: $str = "Hello World! How are you?"
Output: "are Hello How World! you?"
Example 3
Input: $str = "Hello"
Output: "Hello"
Example 4
Input: $str = "Hello, World! How are you?"
Output: "are Hello, How World! you?"
Example 5
Input: $str = "I have 2 apples and 3 bananas!"
Output: "2 3 and apples bananas! have I"
This is the kind of problem both Raku and Perl can solve in one line.
The Raku version is especially compact and easy to read. We get the input from the
first command-line argument, @*ARGS[0]. It is split up into words with the aptly named
.words(). The words are sorted into ascending alphabetical order with .sort(). One
small hurdle is that the sort must be case-insensitive. (See example 1 where The is output after quick not before brown as we would expect in pure ASCII order.) We can get around
this by converting each word to upper-case while sorting it. We then join the sorted words
together with one space in between using .join(). Luckily, the spec did not require us
to preserve white space. Finally, the result is output with .say().
@*ARGS[0].words.sort({$^a.uc cmp $^b.uc}).join(q{ }).say
The Perl version is actually a little shorter as we can pack code a little tighter but it slightly harder to read IMO.
say join q{ }, sort {uc $a cmp uc $b} split /\s+/, shift