Perl Weekly Challenge 328.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 328.
Task 1: Replace all ?
Submitted by: Mohammad Sajid Anwar
You are given a string containing only lower case English letters and ?.
Write a script to replace all ? in the given string so that the string
doesn’t contain consecutive repeating characters.
Example 1
Input: $str = "a?z"
Output: "abz"
There can be many strings, one of them is "abz".
The choices are 'a' to 'z' but we can't use either 'a' or 'z' to replace
the '?'.
Example 2
Input: $str = "pe?k"
Output: "peak"
Example 3
Input: $str = "gra?te"
Output: "grabte"
A simple straightforward solution is to replace ?
with a
, and increment
it until it differs from the previous and next characters. I use the
autoincrement operator acting on strings and the /e
switch of the
substitution operator, to allow arbitrary Perl expressions in the
replacement, which yields a simple one+ liner.
Examples:
perl -E '
for(@ARGV){$i=$_;1while s/(.?)(\?)(.?)/do{$y="a";++$y while$y eq$1 or $y eq$3;"$1$y$3"}/e;say"$i->$_"}
' a?z pe?k gra?te
Results:
a?z -> abz
pe?k -> peak
gra?te -> grabte
Other examples: Examples:
perl -E '
for(@ARGV){$i=$_;1while s/(.?)(\?)(.?)/do{$y="a";++$y while$y eq$1 or $y eq$3;"$1$y$3"}/e;say"$i->$_"}
' a?a a?b a??a a??b a??c ?a a?
Results:
a?a->aba
a?b->acb
a??a->abca
a??b->abab
a??c->abac
?a->ba
a?->ab
The full code is similar, but with an explicit function to process the replacement and some tests.
1 # Perl weekly challenge 328
2 # Task 1: Replace all ?
3 #
4 # See https://wlmb.github.io/2025/07/03/PWC328/#task-1-replace-all-?
5
6 use v5.36;
7 die <<~"FIN" unless @ARGV;
8 Usage: $0 S1 S2...
9 to replace ? by lowercase letters in the lowercase strings S1 S2...
10 so that no letter repeats.
11 FIN
12 for(@ARGV){
13 say "Expected only lowercase letters and ?'s" unless /^[a-z?]+$/;
14 say("Expected no repeating letters in string: $_"), next if /([a-z])\1/;
15 my $in=$_;
16 1 while s/(.?)(\?)(.?)/replace($1, $3)/e;
17 say "$in -> $_";
18 }
19 sub replace($x, $z){
20 my $y="a";
21 ++$y while $y eq $x or $y eq $z;
22 "$1$y$3"
23 }
Examples:
./ch-1.pl a?z pe?k gra?te a?a a?b a??a a??b a??c ?a a?
Results:
a?z -> abz
pe?k -> peak
gra?te -> grabte
a?a -> aba
a?b -> acb
a??a -> abca
a??b -> abab
a??c -> abac
?a -> ba
a? -> ab
Task 2: Good String
Submitted by: Mohammad Sajid Anwar
You are given a string made up of lower and upper case English letters only.
Write a script to return the good string of the given string. A string is
called good string if it doesn’t have two adjacent same characters, one in
upper case and other is lower case.
UPDATE [2025-07-01]: Just to be explicit, you can only remove pair if they are
same characters, one in lower case and other in upper case, order is not important.
Example 1
Input: $str = "WeEeekly"
Output: "Weekly"
We can remove either, "eE" or "Ee" to make it good.
Example 2
Input: $str = "abBAdD"
Output: ""
We remove "bB" first: "aAdD"
Then we remove "aA": "dD"
Finally remove "dD".
Example 3
Input: $str = "abc"
Output: "abc"
This task may be easily solved by using Perl’s extended patterns. In
particular, (??{ *code* })
allows running some code to build the
regular expression to match. For example, the regular expression
(.)(??{uc($1)})
matches a character followed by its uppercase
counterpart. This allows a simple oneliner:
Examples:
perl -E '
for(@ARGV){$i=$_;1 while(s/(.)(??{$l=lc($1); $l eq $1? uc($1):lc($1)})//);say"$i->$_";}
' WeEeekly abBAdD abc
Results:
WeEeekly->Weekly
abBAdD->
abc->abc
Here I use the regular expression (.)(??{$l=lc($1); $l eq $1?
uc($1):lc($1)})
which matches a lowercase character followed by its
uppercase counterpart and an uppwercase character followed by its
lowercase counterpart. As it is, it only works for alphabetical characters.
I test the code with the same examples but inverting the cases:
perl -E '
for(@ARGV){$i=$_;1 while(s/(.)(??{$l=lc($1); $l eq $1? uc($1):lc($1)})//);say"$i->$_";}
' wEeEEKLY ABbaDd ABC
Results:
wEeEEKLY->wEEKLY
ABbaDd->
ABC->ABC
Upper and lowercase non-alphabetical characters are equal, so it is not clear if they whould be deleted when repeated. The code above would delete them:
perl -E '
for(@ARGV){$i=$_;1 while(s/(.)(??{$l=lc($1); $l eq $1? uc($1):lc($1)})//);say"$i->$_";}
' 12aA23
Results:
12aA23->13
The full code is similar but I don’t delete pairs of repeated non-alphabetical characters:
1 # Perl weekly challenge 328
2 # Task 2: Good String
3 #
4 # See https://wlmb.github.io/2025/07/03/PWC328/#task-2-good-string
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 S1 S2...
8 to convert the strings S1 S2... into good strings
9 without any lowercase (uppercase) letter adjacent to the corresponding
10 uppercase (lowercase) letter.
11 FIN
12 for(@ARGV){
13 my $in=$_;
14 1 while(s/([[:alpha:]])(??{my $l=lc($1); $l eq $1? uc($1):lc($1)})//);
15 say"$in->$_";
16 }
Examples:
./ch-2.pl WeEeekly abBAdD abc wEeEEKLY ABbaDd ABC 12aA23
Results:
WeEeekly->Weekly
abBAdD->
abc->abc
wEeEEKLY->wEEKLY
ABbaDd->
ABC->ABC
12aA23->1223
/;