Perl Weekly Challenge 313.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 313.
Task 1: Broken Keys
Submitted by: Mohammad Sajid Anwar
You have a broken keyboard which sometimes type a character more than once.
You are given a string and actual typed string.
Write a script to find out if the actual typed string is meant for the given string.
Example 1
Input: $name = "perl", $typed = "perrrl"
Output: true
Here "r" is pressed 3 times instead of 1 time.
Example 2
Input: $name = "raku", $typed = "rrakuuuu"
Output: true
Example 3
Input: $name = "python", $typed = "perl"
Output: false
Example 4
Input: $name = "coffeescript", $typed = "cofffeescccript"
Output: true
I can build a regular expression based on the expected string by including one or more repetitions of each letter (appending a ‘+’) and then I can test the typed string against the expression. This yields a one-liner.
Examples:
perl -E '
for my ($n,$t)(@ARGV){($e=$n)=~s/(.)/$1+/g;say "$n, $t -> ", $t=~/$e/?"t":"f"}
' raku rrakuuu python perl coffeescript cofffeescccript
Results:
raku, rrakuuu -> t
python, perl -> f
coffeescript, cofffeescccript -> t
The full code is the same, with a couple of tests:
1 # Perl weekly challenge 313
2 # Task 1: Broken Keys
3 #
4 # See https://wlmb.github.io/2025/03/17/PWC313/#task-1-broken-keys
5 use v5.40;
6 die <<~"FIN" unless @ARGV and @ARGV%2==0;
7 Usage: $0 S1 T1 S2 T2...
8 to check if the strings Tn typed in a broken typewriter
9 correspond to the actual expected strings Sn.
10 FIN
11 for my($name, $typed)(@ARGV){
12 try {
13 die "Only word letters allowed: $name" unless $name=~/^\w+$/;
14 my $expression=$name;
15 $expression=~s/(.)/$1+/g;
16 my $result=($typed=~/$expression/)?"True":"False";
17 say "name=$name, typed=$typed -> $result";
18 }
19 catch($e){
20 say $e;
21 }
22 }
Example:
./ch-1.pl raku rrakuuu python perl coffeescript cofffeescccript
Results:
name=raku, typed=rrakuuu -> True
name=python, typed=perl -> False
name=coffeescript, typed=cofffeescccript -> True
Task 2: Reverse Letters
Submitted by: Mohammad Sajid Anwar
You are given a string.
Write a script to reverse only the alphabetic characters in the string.
Example 1
Input: $str = "p-er?l"
Output: "l-re?p"
Example 2
Input: $str = "wee-k!L-y"
Output: "yLk-e!e-w"
Example 3
Input: $str = "_c-!h_all-en!g_e"
Output: "_e-!g_nel-la!h_c"
I can extract the alphabetic letters and merge
into the original string in the reverse order. I use the fact that
when I iterate over an array, modifying the topic $_
modifies the
actual array element. I assume ASCII letters. This yields a oneliner.
Examples:
perl -E '
for(@ARGV){@a=grep {/[a-zA-Z]/}@s=split "";$_=pop @a for grep {/[a-zA-Z]/}@s; say "$_ -> ", @s;}
' p-er?l wee-k!L-y _c-!h_all-en!g_e
Results:
p-er?l -> l-re?p
wee-k!L-y -> yLk-e!e-w
_c-!h_all-en!g_e -> _e-!g_nel-la!h_c
For the full code I use the POSIX alpha class.
1 # Perl weekly challenge 313
2 # Task 2: Reverse Letters
3 #
4 # See https://wlmb.github.io/2025/03/17/PWC313/#task-2-reverse-letters
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 S1 S2...
8 to reverse the alphabetic letters within the strings Sn
9 FIN
10 for(@ARGV){
11 my @letters=grep {/[[:alpha:]]/} my @characters=split "";
12 $_=pop @letters # modifies @characters
13 for grep {/[[:alpha:]]/} @characters;
14 my $output=join "", @characters;
15 say "$_ -> $output"
16 }
Example:
./ch-2.pl p-er?l wee-k!L-y _c-!h_all-en!g_e
Results:
p-er?l -> l-re?p
wee-k!L-y -> yLk-e!e-w
_c-!h_all-en!g_e -> _e-!g_nel-la!h_c
/;