Perl Weekly Challenge: Week 330

This week, the solutions to both challenges are one-liners in Raku and Perl.

Challenge 1:

Clear Digits

You are given a string containing only lower case English letters and digits.

Write a script to remove all digits by removing the first digit and the closest non-digit character to its left.

Example 1
Input: $str = "cab12"
Output: "c"

Round 1: remove "1" then "b" => "ca2"
Round 2: remove "2" then "a" => "c"
Example 2
Input: $str = "xy99"
Output: ""

Round 1: remove "9" then "y" => "x9"
Round 2: remove "9" then "x" => ""
Example 3
Input: $str = "pa1erl"
Output: "perl"

We get the input from the first command-line argument and assign it to $_ to make the code a little shorter.

In a while loop, we use s/// to successively remove instances of a digit (\d) preceded by a non-digit (\D.)

When all such substitutions have been made, we print whatever is left with say(). A piece of cake!

$_ = @*ARGS[0]; while s/\D\d// {}; .say

(Full code on Github.)

The Perl version is actually slightly shorter.

$_ = shift; while(s/\D\d//) {} say

(Full code on Github.)

Challenge 2:

Title Capital

You are given a string made up of one or more words separated by a single space.

Write a script to capitalise the given title. If the word length is 1 or 2 then convert the word to lowercase otherwise make the first character uppercase and remaining lowercase.

Example 1
Input: $str = "PERL IS gREAT"
Output: "Perl is Great"
Example 2
Input: $str = "THE weekly challenge"
Output: "The Weekly Challenge"
Example 3
Input: $str = "YoU ARE A stAR"
Output: "You Are a Star"

Once again, input is the first command-line qrgument. It is split into a list of words with .words().

Then the list of words is transformed with .map(). For each word, we measure its' length with .chars(). If the length is less than 3, the word is converted into lower-case with .lc(). If the word is longer, no problem. The bountiful standard library of Raku has a method that does exactly what the spec wants to do. .tclc() makes the first letter of a word upper-case and all the other letters lower-case.

The words are .join()ed back together into a string separated by spaces and the whole thing is printed out with .say().

@*ARGS[0].words.map({ $_.chars < 3 ?? $_.lc !! $_.tclc }).join(q{ }).say

(Full code on Github.)

The Perl version needs to work around a few missing Raku features but is still pretty short. Instead of .words() we use split() with non-word characters (\W) as the delimeters. Instead of .tclc(), we convert every word to lower-case and if the length() is greater than 2, use a regular expression to make the first character the word upper-case.

Then as in Raku, the words are join() together with spaces and printed with (say().

say join q{ }, map { $_=lc; length > 2 && s/^(.)/\u$1/; $_} (split /\W+/, shift)

(Full code on Github.)