Perl Weekly Challenge 275.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 275.
Task 1: Broken Keys
Submitted by: Mohammad Sajid Anwar
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
I use grep
to filter the words of the sentence according to a class
of characters made of the keys, and then count the number of
elements. The results fit a oneliner.
Example 1:
perl -E '
($s, @k)=@ARGV;@w=split " ",$s; say "sentence: \"$s\" keys: @k -> ", 0+grep{!/[@k]/i}@w;
' "Perl Weekly Chanllenge" l a
Results:
sentence: "Perl Weekly Chanllenge" keys: l a -> 0
Example 2:
perl -E '
($s, @k)=@ARGV;@w=split " ",$s; say "sentence: \"$s\" keys: @k -> ", 0+grep{!/[@k]/i}@w;
' "Perl and Raku" a
Results:
sentence: "Perl and Raku" keys: a -> 1
Example 3:
perl -E '
($s, @k)=@ARGV;@w=split " ",$s; say "sentence: \"$s\" keys: @k -> ", 0+grep{!/[@k]/i}@w;
' "Well done Team PWC" l o
Results:
sentence: "Well done Team PWC" keys: l o -> 2
Example 4:
perl -E '
($s, @k)=@ARGV;@w=split " ",$s; say "sentence: \"$s\" keys: @k -> ", 0+grep{!/[@k]/i}@w;
' "The joys of polyglottism" T
Results:
sentence: "The joys of polyglottism" keys: T -> 2
The corresponding full code is:
1 # Perl weekly challenge 275
2 # Task 1: Broken Keys
3 #
4 # See https://wlmb.github.io/2024/06/24/PWC275/#task-1-broken-keys
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 "S" K1 K2...
8 to count how many words in the sentence S don't contain the broken keys K1 K2...
9 FIN
10 my ($sentence, @keys)=@ARGV;
11 my @words=split " ",$sentence;
12 say "sentence: \"$sentence\" keys: @keys -> ", 0+grep{!/[@keys]/i}@words;
Examples:
./ch-1.pl "Perl Weekly Chanllenge" l a
./ch-1.pl "Perl and Raku" a
./ch-1.pl "Well done Team PWC" l o
./ch-1.pl "The joys of polyglottism" T
Results:
sentence: "Perl Weekly Chanllenge" keys: l a -> 0
sentence: "Perl and Raku" keys: a -> 1
sentence: "Well done Team PWC" keys: l o -> 2
sentence: "The joys of polyglottism" keys: T -> 2
#+endsrc
Task 2: Replace Digits
Submitted by: Mohammad Sajid Anwar
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'
I use ord
and chr
to map characters to numbers and back, which
yields a oneliner. I deal with possible overflows in the full code
below.
Examples:
perl -E '
for(@ARGV){say "$_ -> ", join "", map{/[0-9]/?chr(ord($c)+$_):($c=$_)}split "", $_;}
' a1c1e1 a1b2c3d4 b2b a16z
Results:
a1c1e1 -> abcdef
a1b2c3d4 -> abbdcfdh
b2b -> bdb
a16z -> abgz
The full code is similar, but has a few checks.
1 # Perl weekly challenge 275
2 # Task 2: Replace Digits
3 #
4 # See https://wlmb.github.io/2024/06/24/PWC275/#task-2-replace-digits
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 S1 S2...
8 to replace digits by the previous character shifted the corresponding
9 number of spaces
10 FIN
11 for(@ARGV){
12 my ($last, $current);
13 my $result=join "", map {($last, $current)=nextchar($last, $_); $current} split "", $_;
14 say "$_ -> $result";
15 }
16 sub nextchar($last, $current){
17 die "Digit before first char" if /[0-9]/ && not defined $last;
18 $current=chr(ord($last)+$current) if /[0-9]/;
19 $last=$current unless /[0-9]/;
20 die "Out of range" unless $current=~/[a-z]/i;
21 return ($last, $current);
22 }
Examples:
./ch-2.pl a1c1e1 a1b2c3d4 b2b a16z
Results:
a1c1e1 -> abcdef
a1b2c3d4 -> abbdcfdh
b2b -> bdb
a16z -> abgz
Other examples:
./ch-2.pl 1 2>&1
./ch-2.pl z1 2>&1
Results:
Digit before first char at ./ch-2.pl line 18.
Out of range at ./ch-2.pl line 21.
Written on June 24, 2024