Perl Weekly Challenge 353.

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

Task 1: Max Words

Submitted by: Mohammad Sajid Anwar
You are given an array of sentences.

Write a script to return the maximum number of words that appear in a single sentence.

Example 1
Input: @sentences = ("Hello world", "This is a test", "Perl is great")
Output: 4

Example 2
Input: @sentences = ("Single")
Output: 1

Example 3
Input: @sentences = ("Short", "This sentence has seven words in total", "A B C",
                     "Just four words here")
Output: 7

Example 4
Input: @sentences = ("One", "Two parts", "Three part phrase", "")
Output: 3

Example 5
Input: @sentences = ("The quick brown fox jumps over the lazy dog", "A",
                     "She sells seashells by the seashore",
                     "To be or not to be that is the question")
Output: 10

I’ll assume the input is in the form of period (“. “) separated sentences, and each sentence is made of space separated words. Then I just have to split the input to get all the sentences, split the sentences to get their words, convert to scalar to get their number and choose the maximum. I can use the max function from List::Util. This takes a one-liner.

Examples:

perl -MList::Util=max -E '
for(@ARGV){say "$_ -> ", max map {0+split " "}split /\.\s*/}
' "Hello world. This is a test. Perl is great." "Single." \
  "Short. This sentence has seven words in total. A B C. Just four words here." \
  "One. Two parts. Three part phrase. ." \
  "The quick brown fox jumps over the lazy dog. A.
   She sells seashells by the seashore. To be or not to be that is the question."

Results:

Hello world. This is a test. Perl is great. -> 4
Single. -> 1
Short. This sentence has seven words in total. A B C. Just four words here. -> 7
One. Two parts. Three part phrase. . -> 3
The quick brown fox jumps over the lazy dog. A.
   She sells seashells by the seashore. To be or not to be that is the question. -> 10

The full code is:

 1  # Perl weekly challenge 353
 2  # Task 1:  Max Words
 3  #
 4  # See https://wlmb.github.io/2025/12/22/PWC353/#task-1-max-words
 5  use v5.36;
 6  use List::Util qw(max);
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 S0 S1...
 9      to find the maximum number of space-separated words in the period
10      separated phrases contained in the strings Sn.
11      FIN
12  for(@ARGV){
13      say "$_ -> ",
14          max                # choose maximum
15          map {0+            # count words
16                   split " " # separate into words
17          }
18          split /\.\s*/      # separate into sentences
19  }
20  

Examples:

./ch-1.pl "Hello world. This is a test. Perl is great." "Single." \
  "Short. This sentence has seven words in total. A B C. Just four words here." \
  "One. Two parts. Three part phrase. ." \
  "The quick brown fox jumps over the lazy dog. A.
   She sells seashells by the seashore. To be or not to be that is the question."

Results:

Hello world. This is a test. Perl is great. -> 4
Single. -> 1
Short. This sentence has seven words in total. A B C. Just four words here. -> 7
One. Two parts. Three part phrase. . -> 3
The quick brown fox jumps over the lazy dog. A.
   She sells seashells by the seashore. To be or not to be that is the question. -> 10

Task 2: Validate Coupon

Submitted by: Mohammad Sajid Anwar
You are given three arrays, @codes, @names and @status.

Write a script to validate codes in the given array.

A code is valid when the following conditions are true:
- codes[i] is non-empty and consists only of alphanumeric
  characters (a-z, A-Z, 0-9) and underscores (_).
- names[i] is one of the following four categories:
  "electronics", "grocery", "pharmacy", "restaurant".
- status[i] is true.
Return an array of booleans indicating validity: output[i]
is true if and only if codes[i], names[i] and status[i] are all valid.

Example 1
Input: @codes  = ("A123", "B_456", "C789", "D@1", "E123")
       @names  = ("electronics", "restaurant", "electronics", "pharmacy", "grocery")
       @status = ("true", "false", "true", "true", "true")
Output: (true, false, true, false, true)

Example 2
Input: @codes  = ("Z_9", "AB_12", "G01", "X99", "test")
       @names  = ("pharmacy", "electronics", "grocery", "electronics", "unknown")
       @status = ("true", "true", "false", "true", "true")
Output: (true, true, false, true, false)

Example 3
Input: @codes  = ("_123", "123", "", "Coupon_A", "Alpha")
       @names  = ("restaurant", "electronics", "electronics", "pharmacy", "grocery")
       @status = ("true", "true", "false", "true", "true")
Output: (true, true, false, true, true)

Example 4
Input: @codes  = ("ITEM_1", "ITEM_2", "ITEM_3", "ITEM_4")
       @names  = ("electronics", "electronics", "grocery", "grocery")
       @status = ("true", "true", "true", "true")
Output: (true, true, true, true)

Example 5
Input: @codes  = ("CAFE_X", "ELEC_100", "FOOD_1", "DRUG_A", "ELEC_99")
       @names  = ("restaurant", "electronics", "grocery", "pharmacy", "electronics")
       @status = ("true", "true", "true", "true", "false")
Output: (true, true, true, true, false)

I assume the input are comma separated strings with the codes, names and statuses. I split them and zip them to make an array of references of the form “[code, name, status]”. I test each against a corresponding regular expression and if all are successful the result is true, otherwise false. Finally, I output all results. This takes a 2.5-liner.

Examples:

perl -MList::Util=zip -E '
for my($c,$n,$s)(@ARGV){say "\n$c\n$n\n$s\n -> ",join ", ",map{($x,$y,$z)=$_->@*;$x=~/^(\w|_)*$/
&&$y=~/^(electronics|grocery|pharmacy|restaurant)$/&&$z=~/^true$/?"T":"F"}(zip map {[split
/,\s*/]} $c, $n, $s)}
' "A123, B_456, C789, D@1, E123" "electronics, restaurant, electronics, pharmacy, grocery" \
  "true, false, true, true, true" \
  \
  "Z_9, AB_12, G01, X99, test" "pharmacy, electronics, grocery, electronics, unknown" \
   "true, true, false, true, true" \
   \
  "_123, 123,, Coupon_A, Alpha" "restaurant, electronics, electronics, pharmacy, grocery" \
  "true, true, false, true, true" \
  \
  "ITEM_1, ITEM_2, ITEM_3, ITEM_4" "electronics, electronics, grocery, grocery" \
  "true, true, true, true" \
  \
  "CAFE_X, ELEC_100, FOOD_1, DRUG_A, ELEC_99" \
  "restaurant, electronics, grocery, pharmacy, electronics" \
  "true, true, true, true, false"

Results:

A123, B_456, C789, D@1, E123
electronics, restaurant, electronics, pharmacy, grocery
true, false, true, true, true
 -> T, F, T, F, T

Z_9, AB_12, G01, X99, test
pharmacy, electronics, grocery, electronics, unknown
true, true, false, true, true
 -> T, T, F, T, F

_123, 123,, Coupon_A, Alpha
restaurant, electronics, electronics, pharmacy, grocery
true, true, false, true, true
 -> T, T, F, T, T

ITEM_1, ITEM_2, ITEM_3, ITEM_4
electronics, electronics, grocery, grocery
true, true, true, true
 -> T, T, T, T

CAFE_X, ELEC_100, FOOD_1, DRUG_A, ELEC_99
restaurant, electronics, grocery, pharmacy, electronics
true, true, true, true, false
 -> T, T, T, T, F

The full code is:

 1  # Perl weekly challenge 353
 2  # Task 2:  Validate Coupon
 3  #
 4  # See https://wlmb.github.io/2025/12/22/PWC353/#task-2-validate-coupon
 5  use v5.36;
 6  use feature qw(try);
 7  use List::Util qw(zip);
 8  die <<~"FIN" unless @ARGV and @ARGV%3==0;
 9      Usage: $0 C0 N0 S0 C1 N1 S1...
10      to validate coupons. Cn, Nn and Sn ares a comma separated strings
11      containing codes, names and status, for the n-th list of coupons.
12      FIN
13  for my($codes, $names, $statuses)(@ARGV){
14      try {
15          my @together=zip map {[split /,\s*/]} $codes, $names, $statuses;
16          my @pass = map {
17              my ($code, $name, $status) = $_->@*;
18              die "Missing code: $codes" unless defined $code;
19              die "Missing name: $names" unless defined $name;
20              die "Missing status: $statuses" unless defined $status;
21              $code =~ /^(\w|_)*$/                                           # valid code?
22                  && $name =~ /^(electronics|grocery|pharmacy|restaurant)$/i # valid name?
23                  && $status =~ /^true$/i                                    # valid status?
24                  ? "True" : "False"
25          } @together;
26          my $pass = join ", ", @pass;
27          say "\n$codes\n$names\n$statuses\n -> $pass\n";
28      }
29      catch($e){ warn $e; }
30  }
31  

Example:

./ch-2.pl \
  "A123, B_456, C789, D@1, E123" "electronics, restaurant, electronics, pharmacy, grocery" \
  "true, false, true, true, true" \
  \
  "Z_9, AB_12, G01, X99, test" "pharmacy, electronics, grocery, electronics, unknown" \
   "true, true, false, true, true" \
   \
  "_123, 123,, Coupon_A, Alpha" "restaurant, electronics, electronics, pharmacy, grocery" \
  "true, true, false, true, true" \
  \
  "ITEM_1, ITEM_2, ITEM_3, ITEM_4" "electronics, electronics, grocery, grocery" \
  "true, true, true, true" \
  \
  "CAFE_X, ELEC_100, FOOD_1, DRUG_A, ELEC_99" \
  "restaurant, electronics, grocery, pharmacy, electronics" \
  "true, true, true, true, false"

/;

Written on December 22, 2025