Perl Weekly Challenge: Week 275
Challenge 1:
Broken Keys
You are given a sentence,
$sentence
and list of broken keys@keys
.Write a script to find out how many words can be
typed fully
.
Example 1
Input: $sentence = "Perl Weekly Challenge", @keys = ('l', 'a')
Output: 0
Example 2
Input: $sentence = "Perl and Raku", @keys = ('a')
Output: 1
Only Perl since the other word two words contain 'a' and can't be typed fully.
Example 3
Input: $sentence = "Well done Team PWC", @keys = ('l', 'o')
Output: 2
Example 4
Input: $sentence = "The joys of polyglottism", @keys = ('T')
Output: 2
The input comes from the command-line where the first argument provides $str
and the
rest @keys
.
A regexp pattern by concatenating (with [~]
) the delimiters of a custom character class
with @keys
.
my $keys = [~] '<[', @keys, ']>';
$str
is split into a list of words with .words()
. The character class we created in the previous
line is interpolated into a regular expression (it has to be surrounded by <>
unlike Perl.) and the i
flag is added to make case-insensitive comparisons. (See example 4.) This is used with .grep()
to filter the list for words that do not contain the regular expression. .elems()
is used to count them and this number is printed out with .say()
.
$str.words.grep({ $_ !~~ m:i/ <$keys> / }).elems.say;
The Perl version works the same except join()
is used instead of [~]
and split()
instead of .words()
.
my $keys = join q{}, ('[', @keys, ']');
say scalar grep { $_ !~ /$keys/i } split /\s+/, $str;
Challenge 2:
Replace Digits
You are given an alphanumeric string,
$str
, where each character is either a letter or a digit.Write a script to replace each digit in the given string with the value of the previous letter plus (digit) places.
Example 1
Input: $str = 'a1c1e1'
Ouput: 'abcdef'
shift('a', 1) => 'b'
shift('c', 1) => 'd'
shift('e', 1) => 'f'
Example 2
Input: $str = 'a1b2c3d4'
Output: 'abbdcfdh'
shift('a', 1) => 'b'
shift('b', 2) => 'd'
shift('c', 3) => 'f'
shift('d', 4) => 'h'
Example 3
Input: $str = 'b2b'
Output: 'bdb'
Example 4
Input: $str = 'a16z'
Output: 'abgz'
my @input = $str.comb;
my $output;
my $current;
This one was easy.
The input was split into a list of characters and for each character...
for @input -> $c {
...if it is a digit, the numerical value of the current non-digit character is found with .ord()
.
The digit is added to it and the result is turned back to a character with .chr()
. This is then appended
to the output.
if $c ~~ /\d/ {
$output ~= chr($current.ord + $c);
If it is not a digit, the character is stored in $current
. This is necessary for cases like e.g. example 4 where
two consecutive digits have to be added to a character.
} else {
$current = $c;
Then the character is appended to the output.
$output ~= $c;
}
}
After all of @input
has been processed, $output
is printed.
say $output;
This is the Perl version:
my @input = split //, $str;
my $output;
my $current;
for my $c (@input) {
if ($c =~ /\d/) {
$output .= chr(ord($current) + $c);
} else {
$current = $c;
$output .= $c;
}
}
say $output;