Perl Weekly Challenge 339.

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

Task 1: Max Diff

Submitted by: Mohammad Sajid Anwar
You are given an array of integers having four or more elements.

Write a script to find two pairs of numbers from this list (four numbers total)
so that the difference between their products is as large as possible.

In the end return the max difference.

With Two pairs (a, b) and (c, d), the product difference is (a * b) - (c * d).


Example 1
Input: @ints = (5, 9, 3, 4, 6)
Output: 42

Pair 1: (9, 6)
Pair 2: (3, 4)
Product Diff: (9 * 6) - (3 * 4) => 54 - 12 => 42

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

Pair 1: (1, -2)
Pair 2: (3, -4)

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

Pair 1: (-1, -2)
Pair 2: (-3, -4)

Example 4
Input: @ints = (10, 2, 0, 5, 1)
Output: 50

Pair 1: (10, 5)
Pair 2: (0, 1)

Example 5
Input: @ints = (7, 8, 9, 10, 10)
Output: 44

Pair 1: (10, 10)
Pair 2: (7, 8)

A simple solution consists of computing all products, subtracting them and choosing the largest value. Care should be taken to avoid duplications when multiplying numbers and when subtracting products of pairs of numbers. Using the Perl Data Language PDL the code takes a two liner.

Examples:

perl -MPDL -MPDL::NiceSlice -E '
for(@ARGV){$x=pdl($_);$p=($x*$x(*));$s=$p-$p(*,*);($i,$j,$k,$l)=$s->ndcoords->mv(0,-1)->dog;
$s=$s->where(($i!=$j)&($i!=$k)&($i!=$l)&($j!=$k)&($j!=$l)&($k!=$l));say "$_ -> ", $s->max;}
' "[5 9 3 4 6]" "[1 -2 3 -4]" "[-3 -1 -2 -4]" "[10 2 0 5 1]" "[7 8 9 10 10]"

Results:

[5 9 3 4 6], -> 42
[1 -2 3 -4] -> 10
[-3 -1 -2 -4] -> 10
[10 2 0 5 1] -> 50
[7 8 9 10 10] -> 44

This solution may be inefficient, as it computes many unnecessary products and subtractions. For example, if all numbers were positive, it should be enough to multiply the pair of largest numbers and subtract the product of the pair of smallest numbers. If all numbers were negative there is a similar solution, but things become more complicated when there are both positive and negative numbers.

The full code is:

 1  # Perl weekly challenge 339
 2  # Task 1:  Max Diff
 3  #
 4  # See https://wlmb.github.io/2025/09/15/PWC339/#task-1-max-diff
 5  use v5.36;
 6  use feature qw(try);
 7  use PDL;
 8  use PDL::NiceSlice;
 9  die <<~"FIN" unless @ARGV;
10      Usage: $0 A0 A1...
11      to find the maximum difference between products of disctinct
12      elements of the arrays A0, A1... Each array is input as a string
13      of the form "[X0 X1...]" that can be read by PDL
14      FIN
15  for(@ARGV){
16      try {
17          my $in=pdl($_);
18  	die "Expected four or more numbers" unless $in->dim(0)>=4;
19          my $products=$in*$in(*1);
20          my $diffs=$products-$products(*1,*1);  # Xi*Xj-Xk*Xl
21          my ($i, $j, $k, $l) = $diffs->ndcoords->mv(0,-1)->dog; #coordinates into ndarray $diffs
22          $diffs=$diffs->where(
23              ($i!=$j)&($i!=$k)&($i!=$l)
24              &($j!=$k)&($j!=$l)
25              &($k!=$l));  # select elements with no repeating coordinates
26          say "$_ -> ", $diffs->max;
27      }
28      catch($e){
29          warn $e;
30      }
31  }

Example:

./ch-1.pl "[5 9 3 4 6]" "[1 -2 3 -4]" "[-3 -1 -2 -4]" "[10 2 0 5 1]" "[7 8 9 10 10]"

Results:

[5 9 3 4 6] -> 42
[1 -2 3 -4] -> 10
[-3 -1 -2 -4] -> 10
[10 2 0 5 1] -> 50
[7 8 9 10 10] -> 44

Task 2: Peak Point

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

Write a script to find the peak point gained.


Example 1
Input: @gain = (-5, 1, 5, -9, 2)
Output: 1

start: 0
1st change:  0 + (-5) = -5
2nd change: -5 + 1    = -4
3rd change: -4 + 5    = 1
4th change:  1 + (-9) = -8
5th change: -8 + 2    = -6

max(0, -5, -4, 1, -8, -6) = 1

Example 2
Input: @gain = (10, 10, 10, -25)
Output: 30

start: 0
1st change:  0 + 10    = 10
2nd change: 10 + 10    = 20
3rd change: 20 + 10    = 30
4th change: 30 + (-25) = 5

max(0, 10, 20, 30, 5) = 30

Example 3
Input: @gain = (3, -4, 2, 5, -6, 1)
Output: 6

start: 0
1st change:  0 + 3    = 3
2nd change:  3 + (-4) = -1
3rd change: -1 + 2    = 1
4th change:  1 + 5    = 6
5th change:  6 + (-6) = 0
6th change:  0 + 1    = 1

max(0, 3, -1, 1, 6, 0, 1) = 6

Example 4
Input: @gain = (-1, -2, -3, -4)
Output: 0

start: 0
1st change:  0 + (-1) = -1
2nd change: -1 + (-2) = -3
3rd change: -3 + (-3) = -6
4th change: -6 + (-4) = -10

max(0, -1, -3, -6, -10) = 0

Example 5
Input: @gain = (-10, 15, 5)
Output: 10

start: 0
1st change:   0 + (-10) = -10
2nd change: -10 + 15    = 5
3rd change:   5 + 5     = 10

max(0, -10, 5, 10) = 10

I have to compute the cumulative sums of the gains and then find the maximum of the resulting array. Using PDL and the function cumusumover this yields a half-liner.

perl -MPDL -E '
for(@ARGV){say "$_ -> ",append(0,pdl($_))->cumusumover->max}
' "[-5 1 5 -9 2]" "[10 10 10 -25]" "[3 -4 2 5 -6 1]" "[-1 -2 -3 -4]" "[-10 15 5]"

Results:

[-5 1 5 -9 2] -> 1
[10 10 10 -25] -> 30
[3 -4 2 5 -6 1] -> 6
[-1 -2 -3 -4] -> 0
[-10 15 5] -> 10

The full code is:

 1  # Perl weekly challenge 339
 2  # Task 2:  Peak Point
 3  #
 4  # See https://wlmb.github.io/2025/09/15/PWC339/#task-2-peak-point
 5  use v5.36;
 6  use feature qw(try);
 7  use PDL;
 8  die <<~"FIN" unless @ARGV;
 9      Usage: $0 G0 G1...
10      to find the maximum value of the cumulative sums of the gains
11      in arrays G0, G1... Each argument is a string of the form "[g0 g1...]"
12      that may be understood by PDL, where gn is the gain in step n.
13      FIN
14  for(@ARGV){
15      try{
16          say "$_ -> ", append(0,pdl($_))->cumusumover->max
17      }
18      catch($e){
19          warn $e;
20      }
21  }

Example:

./ch-2.pl "[-5 1 5 -9 2]" "[10 10 10 -25]" "[3 -4 2 5 -6 1]" "[-1 -2 -3 -4]" "[-10 15 5]"

Results:

[-5 1 5 -9 2] -> 1
[10 10 10 -25] -> 30
[3 -4 2 5 -6 1] -> 6
[-1 -2 -3 -4] -> 0
[-10 15 5] -> 10

/;

Written on September 15, 2025