Perl Weekly Challenge 336.

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

Task 1: Equal Group

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

Write a script to return true if the given array can be divided
into one or more groups: each group must be of the same size as the others,
with at least two members, and with all members having the same value.


Example 1
Input: @ints = (1,1,2,2,2,2)
Output: true

Groups: (1,1), (2,2), (2,2)

Example 2
Input: @ints = (1,1,1,2,2,2,3,3)
Output: false

Groups: (1,1,1), (2,2,2), (3,3)

Example 3
Input: @ints = (5,5,5,5,5,5,7,7,7,7,7,7)
Output: true

Groups: (5,5,5,5,5,5), (7,7,7,7,7,7)

Example 4
Input: @ints = (1,2,3,4)
Output: false

Example 5
Input: @ints = (8,8,9,9,10,10,11,11)
Output: true

Groups: (8,8), (9,9), (10,10), (11,11)

In the examples all numbers of the same kind are consecutive. If it is not required, then a simple solution is to count with a hash the appearances of all distinct numbers and then check they have a common divisor greater than 1. I can use gcd from Math::Prime::Util. This yields a simple oneliner.

Examples:

perl -MMath::Prime::Util=gcd  -E '
for(@ARGV){my %c; $c{$_}++ for split " "; say "$_ -> ", gcd(values %c)>1?"T":"F"}
' "1 1 2 2 2 2" "1 1 1 2 2 2 3 3" "5 5 5 5 5 5 7 7 7 7 7 7" "1 2 3 4" "8 8 9 9 10 10 11 11"

Results:

1 1 2 2 2 2 -> T
1 1 1 2 2 2 3 3 -> F
5 5 5 5 5 5 7 7 7 7 7 7 -> T
1 2 3 4 -> F
8 8 9 9 10 10 11 11 -> T

Actually, the strings may contain arbitrary words, not only numbers:

perl -MMath::Prime::Util=gcd  -E '
for(@ARGV){my %c; $c{$_}++ for split " "; say "$_ -> ", gcd(values %c)>1?"T":"F"}
' "a a b b b b" "a a a b b b c c" "e e e e e e g g g g g g" "a b c d" "h h i i ja ja kb kb"

Results:

a a b b b b -> T
a a a b b b c c -> F
e e e e e e g g g g g g -> T
a b c d -> F
h h i i ja ja kb kb -> T

The corresponding full code is:

 1  # Perl weekly challenge 336
 2  # Task 1:  Equal Group
 3  #
 4  # See https://wlmb.github.io/2025/08/25/PWC336/#task-1-equal-group
 5  use v5.36;
 6  use Math::Prime::Util qw(gcd);
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 S1 S2...
 9      to find if the space separated numbers Nj within the string Ni
10      may be grouped into equal sized groups of two or more elements.
11      FIN
12  for(@ARGV){
13      my %count;
14      $count{$_}++ for split " ";
15      say "$_ -> ", gcd(values %count) > 1?"True":"False";
16  }

Example:

./ch-1.pl  "1 1 2 2 2 2" "1 1 1 2 2 2 3 3" "5 5 5 5 5 5 7 7 7 7 7 7" \
           "1 2 3 4" "8 8 9 9 10 10 11 11"

Results:

1 1 2 2 2 2 -> True
1 1 1 2 2 2 3 3 -> False
5 5 5 5 5 5 7 7 7 7 7 7 -> True
1 2 3 4 -> False
8 8 9 9 10 10 11 11 -> True

Task 2: Final Score

Submitted by: Mohammad Sajid Anwar
You are given an array of scores by a team.

Write a script to find the total score of the given team. The score
can be any integer, +, C or D. The + adds the sum of previous two
scores. The score C invalidates the previous score. The score D will
double the previous score.

Example 1
Input: @scores = ("5","2","C","D","+")
Output: 30

Round 1: 5
Round 2: 5 + 2
Round 3: 5 (invalidate the previous score 2)
Round 4: 5 + 10 (double the previous score 5)
Round 5: 5 + 10 + 15 (sum of previous two scores)

Total Scores: 30

Example 2
Input: @scores = ("5","-2","4","C","D","9","+","+")
Output: 27

Round 1: 5
Round 2: 5 + (-2)
Round 3: 5 + (-2) + 4
Round 4: 5 + (-2) (invalidate the previous score 4)
Round 5: 5 + (-2) + (-4) (double the previous score -2)
Round 6: 5 + (-2) + (-4) + 9
Round 7: 5 + (-2) + (-4) + 9 + 5 (sum of previous two scores)
Round 8: 5 + (-2) + (-4) + 9 + 5 + 14 (sum of previous two scores)

Total Scores: 27

Example 3
Input: @scores = ("7","D","D","C","+","3")
Output: 45

Round 1: 7
Round 2: 7 + 14 (double the previous score 7)
Round 3: 7 + 14 + 28 (double the previous score 14)
Round 4: 7 + 14 (invalidate the previous score 28)
Round 5: 7 + 14 + 21 (sum of previous two scores)
Round 6: 7 + 14 + 21 + 3

Total Scores: 45

Example 4
Input: @scores = ("-5","-10","+","D","C","+")
Output: -55

Round 1: (-5)
Round 2: (-5) + (-10)
Round 3: (-5) + (-10) + (-15) (sum of previous two scores)
Round 4: (-5) + (-10) + (-15) + (-30) (double the previous score -15)
Round 5: (-5) + (-10) + (-15) (invalidate the previous score -30)
Round 6: (-5) + (-10) + (-15) + (-25) (sum of previous two scores)

Total Scores: -55

Example 5
Input: @scores = ("3","6","+","D","C","8","+","D","-2","C","+")
Output: 128

Round  1: 3
Round  2: 3 + 6
Round  3: 3 + 6 + 9 (sum of previous two scores)
Round  4: 3 + 6 + 9 + 18 (double the previous score 9)
Round  5: 3 + 6 + 9 (invalidate the previous score 18)
Round  6: 3 + 6 + 9 + 8
Round  7: 3 + 6 + 9 + 8 + 17 (sum of previous two scores)
Round  8: 3 + 6 + 9 + 8 + 17 + 34 (double the previous score 17)
Round  9: 3 + 6 + 9 + 8 + 17 + 34 + (-2)
Round 10: 3 + 6 + 9 + 8 + 17 + 34 (invalidate the previous score -2)
Round 11: 3 + 6 + 9 + 8 + 17 + 34 + 51 (sum of previous two scores)

Total Scores: 128

I assume the input is in a space separated string. I compare each entry to the possible type and follow instructions. At the end I sum (from List::Util) all scores and print the result. This yields a two-liner.

Examples:

perl -MList::Util=sum -E '
for(@ARGV){my @s; for(split " "){/\+/&&push @s, $s[-1]+$s[-2];
/D/&&push @s,$s[-1]*2;/C/&&pop@s;/\d/&&push @s,$_} say "$_ -> ", sum @s}
' -- "5 2 C D +" "5 -2 4 C D 9 + +" "7 D D C + 3" "-5 -10 + D C +" "3 6 + D C 8 + D -2 C +"

Results:

5 2 C D + -> 30
5 -2 4 C D 9 + + -> 27
7 D D C + 3 -> 45
-5 -10 + D C + -> -55
3 6 + D C 8 + D -2 C + -> 128

I assumed that the presence of any digit indicates a number.

The full code includes some checks and replaces missing values by 0:

 1  # Perl weekly challenge 336
 2  # Task 2:  Final Score
 3  #
 4  # See https://wlmb.github.io/2025/08/25/PWC336/#task-2-final-score
 5  use v5.36;
 6  use List::Util qw(sum0);
 7  use feature qw(try);
 8  die <<~"FIN" unless @ARGV;
 9      Usage: $0 S1 S2...
10      to perform the space separated operations Oj  in strings Si
11      and print the resulting score.
12      The operations are
13         a number, push it
14         +, push the sum of the last two numbers
15         C, clear the last number
16         D, push twice the last number
17      FIN
18  for(@ARGV){
19      my @scores;
20      try {
21          for(split " "){
22              push(@scores, ($scores[-1]//0)+($scores[-2]//0)), next if /^\+$/;
23              push(@scores, ($scores[-1]//0)*2), next if /^D|d$/;
24              @scores&&pop(@scores), next if /^C|c$/;
25              push(@scores, $_), next if /^(\+|-)?\d+$/;
26              die "Expected +, D, C or number: $_";
27          }
28          say "$_ -> ", sum0 @scores;
29      } catch($e) {
30          say $e;
31      }
32  }

Examples:

./ch-2.pl "5 2 C D +" "5 -2 4 C D 9 + +" "7 D D C + 3" "-5 -10 + D C +" "3 6 + D C 8 + D -2 C +"

Results:

5 2 C D + -> 30
5 -2 4 C D 9 + + -> 27
7 D D C + 3 -> 45
-5 -10 + D C + -> -55
3 6 + D C 8 + D -2 C + -> 128

/;

Written on August 25, 2025