Perl Weekly Challenge 280.

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

Task 1: Twice Appearance

Submitted by: Mohammad Sajid Anwar
You are given a string, $str, containing lowercase English letters only.

Write a script to print the first letter that appears twice.

Example 1
Input: $str = "acbddbca"
Output: "d"
Example 2
Input: $str = "abccd"
Output: "c"
Example 3
Input: $str = "abcdabbb"
Output: "a"

I can split the strings in letters, count them in a hash and stop when any count reaches 2. This yields a one-liner:

Examples:

perl -E 'for(@ARGV){my %c;print "$_ -> ";for(split ""){say($_),last if ++$c{$_}==2}}
' acbddbca abccd abcdabbb

Results:

acbddbca -> d
abccd -> c
abcdabbb -> a

The full code is:

 1  # Perl weekly challenge 280
 2  # Task 1:  Twice Appearance
 3  #
 4  # See https://wlmb.github.io/2024/07/29/PWC280/#task-1-twice-appearance
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 S1 S2...
 8      to print the first duplicated letter in the strings S1 S2...
 9      FIN
10  for(@ARGV){
11      my %count;
12      warn("Expected lower case letters only: $_"), next unless /^[a-z]*$/;
13      print "$_ -> ";
14      for(split ""){
15          say($_),last if ++$count{$_}==2;
16      }
17  }

Examples:

./ch-1.pl acbddbca abccd abcdabbb

Results:

acbddbca -> d
abccd -> c
abcdabbb -> a

Other examples:

./ch-1.pl 2>&1 aA 123 abc

Task 2: Count Asterisks

Submitted by: Mohammad Sajid Anwar
You are given a string, $str, where every two consecutive vertical bars are
grouped into a pair.

Write a script to return the number of asterisks, *, excluding any between
each pair of vertical bars.

Example 1
Input: $str = "p|*e*rl|w**e|*ekly|"
Ouput: 2

The characters we are looking here are "p" and "w**e".
Example 2
Input: $str = "perl"
Ouput: 0
Example 3
Input: $str = "th|ewe|e**|k|l***ych|alleng|e"
Ouput: 5

The characters we are looking here are "th", "e**", "l***ych" and "e".

I can use a regular expression to remove pairs of bars and anything in between. To this end, I should use a non-greedy match. Then I can use tr to count the remaining asterisks. I have to escape the bars to remove their special meaning. This yields a one-liner.

Examples:

perl -E 'for(@ARGV){print "$_ -> "; s/\|.*?\|//g; say tr/*//}
'   "p|*e*rl|w**e|*ekly|" "perl" "th|ewe|e**|k|l***ych|alleng|e"

Results:

p|*e*rl|w**e|*ekly| -> 2
perl -> 0
th|ewe|e**|k|l***ych|alleng|e -> 5

The corresponding full code is:

 1  # Perl weekly challenge 280
 2  # Task 2:  Count Asterisks
 3  #
 4  # See https://wlmb.github.io/2024/07/29/PWC280/#task-2-count-asterisks
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 S1 S2...
 8      to count the asterisks in the strings S1 S2... that are not within
 9      pairs of vertical bars.
10      FIN
11  for(@ARGV){
12      print "$_ -> ";
13      s/\|.*?\|//g;
14      say tr/*//
15  }
16  
17  

Example:

./ch-2.pl "p|*e*rl|w**e|*ekly|" "perl" "th|ewe|e**|k|l***ych|alleng|e"

Results:

p|*e*rl|w**e|*ekly| -> 2
perl -> 0
th|ewe|e**|k|l***ych|alleng|e -> 5
Written on July 29, 2024