Perl Weekly Challenge 329.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 329.

Task 1: Counter Integers

Submitted by: Mohammad Sajid Anwar
You are given a string containing only lower case
English letters and digits.

Write a script to replace every non-digit character
with a space and then return all the distinct integers left.


Example 1
Input: $str = "the1weekly2challenge2"
Output: 1, 2

2 is appeared twice, so we count it one only.

Example 2
Input: $str = "go21od1lu5c7k"
Output: 21, 1, 5, 7

Example 3
Input: $str = "4p3e2r1l"
Output: 4, 3, 2, 1

I can split the string on the letters and use uniqint from List::Util to choose the resulting distinct integers after removing the possible leading blank substring. The result fits a one-liner.

Examples:

perl -MList::Util=uniqint -E '
say "$_ -> ", join " ", uniqint grep {!/^$/} split /[a-z]+/, $_ for @ARGV;
' the1weekly2challenge2 go21od1lu5c7k 4p3e2r1l

Results:

the1weekly2challenge2 -> 1 2
go21od1lu5c7k -> 21 1 5 7
4p3e2r1l -> 4 3 2 1

The corresponding full code is:

 1  # Perl weekly challenge 329
 2  # Task 1:  Counter Integers
 3  #
 4  # See https://wlmb.github.io/2025/07/07/PWC329/#task-1-counter-integers
 5  use v5.36;
 6  use List::Util qw(uniqint);
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 S1 S2...
 9      to find distinct integers within the strings Sn.
10      FIN
11  for(@ARGV){
12      say("Only lowercase letters and digits allowed: $_"), next unless /^[a-z0-9]*$/;
13      say "$_ -> ", join " ", uniqint grep {!/^$/} split /[a-z]+/, $_;
14  }

Examples:

./ch-1.pl  the1weekly2challenge2 go21od1lu5c7k 4p3e2r1l

Results:

the1weekly2challenge2 -> 1 2
go21od1lu5c7k -> 21 1 5 7
4p3e2r1l -> 4 3 2 1

Task 2: Nice 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 longest substring of the give string
which is nice. A string is nice if, for every letter of the alphabet
that the string contains, it appears both in uppercase and lowercase.


Example 1
Input: $str = "YaaAho"
Output: "aaA"

Example 2
Input: $str = "cC"
Output: "cC"

Example 3
Input: $str = "A"
Output: ""

No nice string found.

A string is nice if its first letter x is repeated in its opposite case and if the remaining letters after removing all instances of x and its opposite case form a nice string. This yields an iterative test for niceness. I make a routine to test for niceness and include it within a regular expression to generate all nice subsequences. I use the (??{...}) constructs to execute code within a regular expression and the (*ACCEPT) and (*FAIL) assertions to succeed or fail when a substring is nice or not. Then I let the regular expression machinery produce all the nice substrings. I pick the longest using max_by from List::UtilsBy. This yields a three liner.

Examples:

perl -MList::UtilsBy=max_by -E '
say "$_ -> ",max_by {length} /(.+)(??{n($1)?"(*ACCEPT)":"(*FAIL)"})/g for @ARGV;
sub n($s){for($s){while(1){return 1 if /^$/;/^(.)(.*)/;$x=lc($1);$X=uc($1);
return 0 unless /$x/ && /$X/;s/$x|$X//g;}}}
' YaaAho cC A

Results:

YaaAho -> aaA
cC -> cC
A ->

Other examples, with more than one nice substring each:

perl -MList::UtilsBy=max_by -E '
say "$_ -> ",max_by {length} /(.+)(??{n($1)?"(*ACCEPT)":"(*FAIL)"})/g for @ARGV;
sub n($s){for($s){while(1){return 1 if /^$/;/^(.)(.*)/;$x=lc($1);$X=uc($1);
return 0 unless /$x/ && /$X/;s/$x|$X//g;}}}
' aA aAabcC aAbcCC

Results:

aA -> aA
aAabcC -> aAa
aAbcCC -> cCC

The full code is

 1  # Perl weekly challenge 329
 2  # Task 2:  Nice String
 3  #
 4  # See https://wlmb.github.io/2025/07/07/PWC329/#task-2-nice-string
 5  use v5.36;
 6  use List::UtilsBy qw(max_by);
 7  say "$_ -> ",max_by {length} /(.+)(??{nice($1)?"(*ACCEPT)":"(*FAIL)"})/g for @ARGV;
 8  sub nice($s){
 9      for($s){                                # set the topic
10          while(1){
11              return 1 if /^$/;               # null strings are nice
12              /^(.)(.*)/;                     # capture first character and rest
13              my ($lc, $UC)=(lc($1), uc($1));
14              return 0 unless /$lc/ && /$UC/; # check both cases are present in string
15              s/$lc|$UC//g;                   # remove already tested letters
16          }
17      }
18  }

Examples:

./ch-2.pl YaaAho cC A aA aAabcC aAbcCC

Results:

YaaAho -> aaA
cC -> cC
A ->
aA -> aA
aAabcC -> aAa
aAbcCC -> cCC

/;

Written on July 7, 2025