Perl Weekly Challenge 396.

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

Task 1: Finishing Order

Submitted by: Mohammad Sajid Anwar
You are given two array of integers, @order and @friends.

The @order (size n) contains every integer from 1 to n
exactly once. The @friends contains ID in sorted in strictly
increasing order.

Write a script to return the array containing IDs in
finishing order.

Example 1
Input: @order = (3, 1, 4, 2, 5)
       @friends = (1, 2, 4)
Output: (1, 4, 2)

ID 1 finished 2nd.
ID 4 finished 3rd.
ID 2 finished 4th.

Example 2
Input: @order = (5, 4, 3, 2, 1)
       @friends = (1, 3, 5)
Output: (5, 3, 1)

ID 5 finished 1st.
ID 3 finished 3rd.
ID 1 finished 5th.

Example 3
Input: @order = (2, 4, 1, 3)
       @friends = (1, 2, 3, 4)
Output: (2, 4, 1, 3)

ID 2 finished 1st.
ID 4 finished 2nd.
ID 1 finished 3rd.
ID 3 finished 4th.

Example 4
Input: @order = (4, 1, 3, 2)
       @friends = (3)
Output: (3)

Example 5
Input: @order = (1, 3, 2, 6, 5, 4)
       @friends = (1, 2, 3)
Output: (1, 3, 2)

ID 1 finished 1st.
ID 3 finished 2nd.
ID 2 finished 3rd.


I assume the inputs lists are given as space separated lists of numbers in @ARGV. I make a map ids to places and use it to sort_by (from List__UtilsBy) the array of ids. The result takes a two-liner.

Examples:

perl -MList::UtilsBy=sort_by -E '
for my ($x,$y)(@ARGV){($p,$q)=map{[split" "]}$x,$y;$i=1; @l=();
$l[$_]=$i++ for@$p;say"$x; $y -> ", join " ", sort_by{$l[$_]}@$q}
' "3 1 4 2 5" "1 2 4" "5 4 3 2 1" "1 3 5" "2 4 1 3" "1 2 3 4" \
  "4 1 3 2" "3" "1 3 2 6 5 4" "1 2 3"

Results:

3 1 4 2 5; 1 2 4 -> 1 4 2
5 4 3 2 1; 1 3 5 -> 5 3 1
2 4 1 3; 1 2 3 4 -> 2 4 1 3
4 1 3 2; 3 -> 3
1 3 2 6 5 4; 1 2 3 -> 1 3 2

The full code is:

 1  # Perl weekly challenge 396
 2  # Task 1:  Finishing Order
 3  #
 4  # See https://wlmb.github.io/2026/10/19/PWC396/#task-1-finishing-order
 5  use v5.36;
 6  use feature qw(try);
 7  use List::UtilsBy qw(sort_by);
 8  die <<~"FIN" unless @ARGV && @ARGV%2==0;
 9      Usage: $0 O0 F0 O1 F1...
10      to find the order of arrival of our friends Fn given
11      the order of arrival On. Fn and On are space separated lists
12      of integers.
13      FIN
14  for my ($order_string, $friends_string)(@ARGV){
15      my ($order, $friends)=map {[split " "]} $order_string, $friends_string;
16      my $i=1;
17      my %map;
18      $map{$_} = $i++ for @$order;
19      for(@$friends){
20          die "Friend is unknown: $_" unless defined $map{$_};
21      }
22      say"$order_string; $friends_string -> ",
23          join " ", sort_by{$map{$_}} @$friends;
24  }

Examples:

./ch-1.pl "3 1 4 2 5" "1 2 4" "5 4 3 2 1" "1 3 5" "2 4 1 3" "1 2 3 4" \
          "4 1 3 2" "3" "1 3 2 6 5 4" "1 2 3"

Results:

3 1 4 2 5; 1 2 4 -> 1 4 2
5 4 3 2 1; 1 3 5 -> 5 3 1
2 4 1 3; 1 2 3 4 -> 2 4 1 3
4 1 3 2; 3 -> 3
1 3 2 6 5 4; 1 2 3 -> 1 3 2

An advantage of using a hash for the map is that I can use any string as an id. For example:

./ch-1.pl "Ana Beto Carlos David Elías" "Elías Carlos Ana"

Results:

Ana Beto Carlos David Elías; Elías Carlos Ana -> Ana Carlos Elías

Task 2: Trionic Array

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

Write a script to return true if the given array is Trionic
otherwise return false.

An array is trionic if there exist indices 0 < p < q < n − 1
such that arr[0…p] is strictly increasing, arr[p…q] is
strictly decreasing, and arr[q…n − 1] is strictly
increasing.

Example 1
Input: @arr = (1, 3, 5, 4, 2, 6, 8)
Output: true

Choose p = 2 and q = 4
$arr[0..2] = (1, 3, 5) (strictly increasing)
$arr[2..4] = (5, 4, 2) (strictly decreasing)
$arr[4..6] = (2, 6, 8) (strictly increasing)

Valid indices: 0 < p (2) < q (4) < n-1 (6).

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

The first segment (1, 4, 4) contains duplicate adjacent
values, so it is not strictly increasing. No valid p and q
exist to satisfy all three strictly monotonic conditions.

Example 3
Input: @arr = (2, 10, 3, 1, 9)
Output: true

Choose p = 1 and q = 3.
$arr[0..1] = (2, 10)    (strictly increasing)
$arr[1..3] = (10, 3, 1) (strictly decreasing)
$arr[3..4] = (1, 9)     (strictly increasing)

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

This is a standard mountain array (strictly increasing, then
strictly decreasing). There is no second valley (q) that
transitions back into a strictly increasing third segment
before reaching the end of the array.

Example 5
Input: @arr = (1, 3, 6, 4, 2, 7, 8, 4)
Output: false

I compare consecutive elements. If any are equal, the result is false. If not, I count state changes, from initial to increasing to decreasing to increasing again. If there are additional or missing state changes, the result is false. Otherwise, it is true. The result fits a 3-liner.

Examples:

perl -E '
for(@ARGV){@x=split" ";$c=$d=$f=0;for(1..@x-1){$s=$x[$_-1]<=>$x[$_];
$f=1,last if (!$s||$c==0 && $s>0||$c==2&&$s>0);$c=1 if $d==0&&$s<0;$d=1
if $c==1&&$s>0;$c=2 if $d==1&&$s<0;}say "$_ -> ", ($f||$c<2)?"F":"T";}
' "1 3 5 4 2 6 8" "1 4 4 2 1 3 5" "2 10 3 1 9" \
  "1 2 3 4 3 2 1" "1 3 6 4 2 7 8 4"

Results:

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

The full code is:

 1  # Perl weekly challenge 396
 2  # Task 2:  Trionic Array
 3  #
 4  # See https://wlmb.github.io/2026/10/19/PWC396/#task-2-trionic-array
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 L0 L1...
 8      to find if the space separated list Ln is trionic,
 9      i.e., strictly increasing, decreasing and then increasing.
10      FIN
11  for(@ARGV){
12      my @arr = split " ";
13      my ($increasing, $decreasing, $failed) = (0, 0, 0);
14      for(1..@arr-1){
15          my $sign = $arr[$_-1] <=> $arr[$_];
16          $failed=1,last
17              if (!$sign                           # not strictly increasing or decreasing
18                  || $increasing==0 && $sign > 0   # decreasing before increasing
19                  || $increasing==2 && $sign > 0); # decreasing after increasing twice
20          $increasing = 1,next
21              if $decreasing == 0 && $sign < 0;    # first increasing
22          $decreasing = 1,next
23              if $increasing==1 && $sign > 0;      # first decreasing
24          $increasing = 2, next
25              if $decreasing == 1 && $sign<0;      # second increasing
26      }
27      say "$_ -> ", ($failed || $increasing < 2)?"False":"True";
28  }

Examples:

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

Results:

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

/;

Written on October 19, 2026