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
/;