Perl Weekly Challenge 334.

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

Task 1: Range Sum

Submitted by: Mohammad Sajid Anwar
You are given a list integers and pair of indices..

Write a script to return the sum of integers between the given indices (inclusive).


Example 1
Input: @ints = (-2, 0, 3, -5, 2, -1), $x = 0, $y = 2
Output: 1

Elements between indices (0, 2) => (-2, 0, 3)
Range Sum: (-2) + 0 + 3 => 1

Example 2
Input: @ints = (1, -2, 3, -4, 5), $x = 1, $y = 3
Output: -3

Elements between indices (1, 3) => (-2, 3, -4)
Range Sum: (-2) + 3 + (-4) => -3

Example 3
Input: @ints = (1, 0, 2, -1, 3), $x = 3, $y = 4
Output: 2

Elements between indices (3, 4) => (-1, 3)
Range Sum: (-1) + 3 => 2

Example 4
Input: @ints = (-5, 4, -3, 2, -1, 0), $x = 0, $y = 3
Output: -2

Elements between indices (0, 3) => (-5, 4, -3, 2)
Range Sum: (-5) + 4 + (-3) + 2 => -2

Example 5
Input: @ints = (-1, 0, 2, -3, -2, 1), $x = 0, $y = 2
Output: 1

Elements between indices (0, 2) => (-1, 0, 2)
Range Sum: (-1) + 0 + 2 => 1

The task is quite trivial using the Perl Data Language PDL. I slice the array and sumover the elements. The result fits a one-liner.

Examples:

perl -MPDL -MPDL::NiceSlice -E '
for my($i,$x,$y)(@ARGV){say "x=$x y=$y ints=$i -> ", pdl($i)->($x:$y)->sumover}
' "[-2 0 3 -5 2 -1]" 0 2 "[1 -2 3 -4 5]" 1 3 "[1 0 2 -1 3]" 3 4 "[-5 4 -3 2 -1 0]" 0 3 \
  "[-1 0 2 -3 -2 1]" 0 2

Results:

x=0 y=2 ints=[-2 0 3 -5 2 -1] -> 1
x=1 y=3 ints=[1 -2 3 -4 5] -> -3
x=3 y=4 ints=[1 0 2 -1 3] -> 2
x=0 y=3 ints=[-5 4 -3 2 -1 0] -> -2
x=0 y=2 ints=[-1 0 2 -3 -2 1] -> 1

An alternative solution without PDL is also simple, indexing a Perl array and using sum from List::Util. The result fits again a one-liner:

perl -MList::Util=sum -E '
for my($i,$x,$y)(@ARGV){say "x=$x y=$y ints=[$i] -> ", sum((split " ", $i)[$x..$y])}
' -- "-2 0 3 -5 2 -1" 0 2 "1 -2 3 -4 5" 1 3 "1 0 2 -1 3" 3 4 "-5 4 -3 2 -1 0" 0 3 \
  "-1 0 2 -3 -2 1" 0 2

Results:

x=0 y=2 ints=[-2 0 3 -5 2 -1] -> 1
x=1 y=3 ints=[1 -2 3 -4 5] -> -3
x=3 y=4 ints=[1 0 2 -1 3] -> 2
x=0 y=3 ints=[-5 4 -3 2 -1 0] -> -2
x=0 y=2 ints=[-1 0 2 -3 -2 1] -> 1

I use -- as a first argument to allow negative numbers without confusing them with switches.

The full code for the first solution, with some error checking, is

 1  # Perl weekly challenge 334
 2  # Task 1:  Range Sum
 3  #
 4  # See https://wlmb.github.io/2025/08/11/PWC334/#task-1-range-sum
 5  use v5.36;
 6  use PDL;
 7  use feature qw(try);
 8  die <<~"FIN" unless @ARGV and @ARGV%3==0;
 9      Usage: $0 I1 X1 Y1 I2 X2 Y2...
10      to sum elements Xi to Yi of the array Ii.
11      Ii is a string in the format "[i0 i1 i2...]"
12      where the i's are numbers.
13      FIN
14  for my ($s, $x, $y)(@ARGV){
15       try{
16          my $i=pdl($s);
17          my $n=$i->nelem;
18          die "Expected 0<=X<=Y<$n: x=$x, y=$y"
19             unless 0<=$x<=$y<$n;
20          say "x=$x, y=$y, ints=$s -> ", $i->slice([$x,$y])->sumover;
21       }
22       catch($e){
23           say $e;
24       }
25  }

Examples:

./ch-1.pl "[-2 0 3 -5 2 -1]" 0 2 "[1 -2 3 -4 5]" 1 3 "[1 0 2 -1 3]" 3 4 "[-5 4 -3 2 -1 0]" 0 3 \
          "[-1 0 2 -3 -2 1]" 0 2

Results:

x=0, y=2, ints=[-2 0 3 -5 2 -1] -> 1
x=1, y=3, ints=[1 -2 3 -4 5] -> -3
x=3, y=4, ints=[1 0 2 -1 3] -> 2
x=0, y=3, ints=[-5 4 -3 2 -1 0] -> -2
x=0, y=2, ints=[-1 0 2 -3 -2 1] -> 1

Task 2: Nearest Valid Point

Submitted by: Mohammad Sajid Anwar
You are given current location as two integers: x and y. You are also given a list
of points on the grid. A point is considered valid if it shares either the same
x-coordinate or the same y-coordinate as the current location. Write a script to
return the index of the valid point that has the smallest Manhattan distance to
the current location. If multiple valid points are tied for the smallest distance,
return the one with the lowest index. If no valid points exist, return -1.

The Manhattan distance between two points (x1, y1) and (x2, y2) is calculated as:
|x1 - x2| + |y1 - y2|

Example 1
Input: $x = 3, $y = 4, @points ([1, 2], [3, 1], [2, 4], [2, 3])
Output: 2

Valid points: [3, 1] (same x), [2, 4] (same y)

Manhattan distances:
    [3, 1] => |3-3| + |4-1| = 3
    [2, 4] => |3-2| + |4-4| = 1

Closest valid point is [2, 4] at index 2.

Example 2
Input: $x = 2, $y = 5, @points ([3, 4], [2, 3], [1, 5], [2, 5])
Output: 3

Valid points: [2, 3], [1, 5], [2, 5]

Manhattan distances:
    [2, 3] => 2
    [1, 5] => 1
    [2, 5] => 0

Closest valid point is [2, 5] at index 3.

Example 3
Input: $x = 1, $y = 1, @points ([2, 2], [3, 3], [4, 4])
Output: -1

No point shares x or y with (1, 1).

Example 4
Input: $x = 0, $y = 0, @points ([0, 1], [1, 0], [0, 2], [2, 0])
Output: 0

Valid points: all of them

Manhattan distances:
    [0, 1] => 1
    [1, 0] => 1
    [0, 2] => 2
    [2, 0] => 2

Tie between index 0 and 1, pick the smaller index: 0

Example 5
Input: $x = 5, $y = 5, @points ([5, 6], [6, 5], [5, 4], [4, 5])
Output: 0

Valid points: all of them
    [5, 6] => 1
    [6, 5] => 1
    [5, 4] => 1
    [4, 5] => 1

All tie, return the one with the lowest index: 0

I use PDL to read the given point and the array of points. I use orover and whichND to get the indices of valid points, and indexND to get the actual points. I compute the Manhattan distance using abs and sumover. Then I compute the min, and use which and index to get the indices of the closest valid points, and finally I get their min and print the results.

 1  # Perl weekly challenge 334
 2  # Task 2:  Nearest Valid Point
 3  #
 4  # See https://wlmb.github.io/2025/08/11/PWC334/#task-2-nearest-valid-point
 5  use v5.36;
 6  use feature qw(try);
 7  use PDL;
 8  die <<~"FIN" unless @ARGV and @ARGV%2==0;
 9      Usage: $0 F1 P1 F2 P2...
10      to find the index in the array of points Pi of the valid
11      point nearest to Fi. Fi is input as the string "[x y]" and
12      Pi as the string "[[x1 y1][x2 y2]...]"
13      FIN
14  for my ($first_str, $points_str)(@ARGV){
15      try{
16          my ($first, $points)=map{pdl $_}($first_str, $points_str);
17          my $indices=whichND(orover($points==$first));
18          my $valid=$points->mv(-1,0)->indexND($indices)->mv(0,-1);
19          my $manhattan=($valid-$first)->abs->sumover;
20          my $result=-1;
21          if($manhattan->nelem){
22              my $min=$manhattan->min;
23              my $close=which($manhattan==$min);
24              $result=$indices->flat->index($close)->min;
25          }
26          say "given=$first, points=$points -> $result";
27      }
28      catch($e){
29          say $e;
30      }
31  }

Examples:

./ch-2.pl "[3 4]" "[[1 2][3 1][2 4][2 3]]" "[2 5]" "[[3 4][2 3][1 5][2 5]]"  \
          "[1 1]" "[[2 2][3 3][4 4]]"      "[0 0]" "[[0 1][1 0][0 2][2, 0]]" \
          "[5 5]" "[[5 6][6 5][5 4][4 5]]"

Results:

given=[3 4], points=
[
 [1 2]
 [3 1]
 [2 4]
 [2 3]
]
 -> 2
given=[2 5], points=
[
 [3 4]
 [2 3]
 [1 5]
 [2 5]
]
 -> 3
given=[1 1], points=
[
 [2 2]
 [3 3]
 [4 4]
]
 -> -1
given=[0 0], points=
[
 [0 1]
 [1 0]
 [0 2]
 [2 0]
]
 -> 0
given=[5 5], points=
[
 [5 6]
 [6 5]
 [5 4]
 [4 5]
]
 -> 0

I’m sure there must be a more direct way. Anyway, just for fun, I try to compact everything into a two-liner+.

perl -Mfeature=try -MPDL -E '
for my ($f, $p)(map{pdl $_}@ARGV){$i=whichND(orover($p==$f));$v=$p->mv(-1,0)->indexND($i)->mv(0,-1);
$M=($v-$f)->abs->sumover;$r=-1;$m=$M->min,$c=which($M==$m),$r=$i->flat->index($c)->min if $M->nelem;
say "$f,$p->$r";}
' "[3 4]" "[[1 2][3 1][2 4][2 3]]" "[2 5]" "[[3 4][2 3][1 5][2 5]]"  \
          "[1 1]" "[[2 2][3 3][4 4]]"      "[0 0]" "[[0 1][1 0][0 2][2, 0]]" \
          "[5 5]" "[[5 6][6 5][5 4][4 5]]"

Results:

[3 4],
[
 [1 2]
 [3 1]
 [2 4]
 [2 3]
]
->2
[2 5],
[
 [3 4]
 [2 3]
 [1 5]
 [2 5]
]
->3
[1 1],
[
 [2 2]
 [3 3]
 [4 4]
]
->-1
[0 0],
[
 [0 1]
 [1 0]
 [0 2]
 [2 0]
]
->0
[5 5],
[
 [5 6]
 [6 5]
 [5 4]
 [4 5]
]
->0

/;

Written on August 11, 2025