Perl Weekly Challenge: Week 340
Challenge 1:
Duplicate Removals
You are given a string,
$str
, consisting of lowercase English letters.Write a script to return the final string after all duplicate removals have been made. Repeat duplicate removals on the given string until we no longer can.
A duplicate removal consists of choosing two adjacent and equal letters and removing them.
Example 1
Input: $str = 'abbaca'
Output: 'ca'
Step 1: Remove 'bb' => 'aaca'
Step 2: Remove 'aa' => 'ca'
Example 2
Input: $str = 'azxxzy'
Output: 'ay'
Step 1: Remove 'xx' => 'azzy'
Step 2: Remove 'zz' => 'ay'
Example 3
Input: $str = 'aaaaaaaa'
Output: ''
Step 1: Remove 'aa' => 'aaaaaa'
Step 2: Remove 'aa' => 'aaaa'
Step 3: Remove 'aa' => 'aa'
Step 4: Remove 'aa' => ''
Example 4
Input: $str = 'aabccba'
Output: 'a'
Step 1: Remove 'aa' => 'bccba'
Step 2: Remove 'cc' => 'bba'
Step 3: Remove 'bb' => 'a'
Example 5
Input: $str = 'abcddcba'
Output: ''
Step 1: Remove 'dd' => 'abccba'
Step 2: Remove 'cc' => 'abba'
Step 3: Remove 'bb' => 'aa'
Step 4: Remove 'aa' => ''
This is a simple one-liner in Raku. First we get the input from the first command-line argument and
assign it to $_
. This will save some typing in the rest of the code. Then we use a regular expression to match
a character followed by another instance of the same character and using the s///
operator "substitute" them with an
empty string or in other words, delete them. We repeatedly do this in an otherwise empty while
-loop. The loop will
end when there are no more substitutions to be made. We them print whatever is left in $_
with .say()
Because
we are not explicitly stating which variable is the topic of .say()
, we have to provide a semicolon after the while
block to prevent ambiguity.
$_ = @*ARGS[0]; while s/(.)$0// {}; .say
The Perl version is a one-liner too and works in the same way as Raku. It is actually a little shorter whch doesn't happen too often.
$_ = shift; while (s/(.)\1//) {} say
Challenge 2:
Ascending Numbers
You are given a string,
$str
, is a list of tokens separated by a single space. Every token is either a positive number consisting of digits 0-9 with no leading zeros, or a word consisting of lowercase English letters.Write a script to check if all the numbers in the given string are strictly increasing from left to right.
Example 1
Input: $str = "The cat has 3 kittens 7 toys 10 beds"
Output: true
Numbers 3, 7, 10 - strictly increasing.
Example 2
Input: $str = 'Alice bought 5 apples 2 oranges 9 bananas'
Output: false
Example 3
Input: $str = 'I ran 1 mile 2 days 3 weeks 4 months'
Output: true
Example 4
Input: $str = 'Bob has 10 cars 10 bikes'
Output: false
Example 5
Input: $str = 'Zero is 0 one is 1 two is 2'
Output: true
Yet another one-liner in Raku. As in challenge 1, first we get the input from the first command-line argument. We
find all the numbers with .match()
and convert them from match objects back to numbers with the hyper operator ».Int
. This results in an array of numbers, @n
. This is compared to a numerically sorted version of itself. If
the comparison is is True
, we print that using .say()
otherwise we print False
.
my @n = @*ARGS[0].match(/(\d+)/,:g)».Int; (@n ~~ @n.sort({$^a <=> $^b})).say
I tried writing a one-liner in Perl, but it was a little too long to justify the name. Instead look at this:
Like the Raku version, we start by assigning the numbers matched from the input into an array, @n
.
my @n = shift =~ /(\d+)/g;
We set up a variable to hold the result. Initially, this will be true
.
my $result = true;
Because we are using modern Perls new true
and false
builtin we have to add these lines to the top of the script.
use builtin qw/ true false /;
no warnings qw/ experimental::builtin /;
Instead of comparing this array with a sorted version of itself, we look through all of its elements starting from the second and compare each element to the one before it.
for my $i (1 .. scalar @n - 1) {
If it is lesser, the array is not strictly increasing so we set $result
to false
and stop processing.
if ($n[$i] < $n[$i- 1]) {
$result = false;
last
}
}
Depending on the value of $result
, we print true or false.
say $result ? "true" : "false";