Perl Weekly Challenge 251.

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

Task 1: Concatenation Value

Submitted by: Mohammad S Anwar
You are given an array of integers, @ints.

Write a script to find the concatenation value of the given array.

The concatenation of two numbers is the number formed by concatenating their
numerals.

For example, the concatenation of 10, 21 is 1021.
The concatenation value of @ints is initially equal to 0.
Perform this operation until @ints becomes empty:

If there exists more than one number in @ints, pick the first element
and last element in @ints respectively and add the value of their
concatenation to the concatenation value of @ints, then delete the
first and last element from @ints.

If one element exists, add its value to the concatenation value of
@ints, then delete it.

Example 1
Input: @ints = (6, 12, 25, 1)
Output: 1286

1st operation: concatenation of 6 and 1 is 61
2nd operation: concaternation of 12 and 25 is 1225

Concatenation Value => 61 + 1225 => 1286
Example 2
Input: @ints = (10, 7, 31, 5, 2, 2)
Output: 489

1st operation: concatenation of 10 and 2 is 102
2nd operation: concatenation of 7 and 2 is 72
3rd operation: concatenation of 31 and 5 is 315

Concatenation Value => 102 + 72 + 315 => 489
Example 3
Input: @ints = (1, 2, 10)
Output: 112

1st operation: concatenation of 1 and 10 is 110
2nd operation: only element left is 2

Concatenation Value => 110 + 2 => 112

Perl nicely converts strings, which may be concatenated, to numbers, which may be added. Furthermore, an undef string is conveniently interpreted as a null string (when we are not strict). The shift and pop operators allow taking the first and las elements our of an array. These allow an extremely compact one-liner:

Example 1:

perl -E '@x=@ARGV; $tot+=shift(@x).pop(@x) while(@x); say "@ARGV -> $tot"' 6 12 25 1

Results:

6 12 25 1 -> 1286

Example 2:

perl -E '@x=@ARGV; $tot+=shift(@x).pop(@x) while(@x); say "@ARGV -> $tot"' 10 7 31 5 2 2

Results:

10 7 31 5 2 2 -> 489

Example 3:

perl -E '@x=@ARGV; $tot+=shift(@x).pop(@x) while(@x); say "@ARGV -> $tot"' 1 2 10

Results:

1 2 10 -> 112

The full code is slightly more careful for the case of an odd number of elements:

 1  # Perl weekly challenge 251
 2  # Task 1:  Concatenation Value
 3  #
 4  # See https://wlmb.github.io/2024/01/08/PWC251/#task-1-concatenation-value
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 N1 [N2...]
 8      to concatenate and add the numbers N_1 . N_k + N_2 . N_{k-1} +...
 9      FIN
10  my $tot=0;
11  my @ints=@ARGV;
12  $tot += shift(@ints).(pop(@ints)//"") while(@ints);
13  say "@ARGV -> $tot";

Examples:

./ch-1.pl 6 12 25 1
./ch-1.pl 10 7 31 5 2 2
./ch-1.pl 1 2 10

Results:

6 12 25 1 -> 1286
10 7 31 5 2 2 -> 489
1 2 10 -> 112

Task 2: Lucky Numbers

Submitted by: Mohammad S Anwar
You are given a m x n matrix of distinct numbers.

Write a script to return the lucky number, if there is one, or -1 if not.

A lucky number is an element of the matrix such that it is
the minimum element in its row and maximum in its column.

Example 1
Input: $matrix = [ [ 3,  7,  8],
                   [ 9, 11, 13],
                   [15, 16, 17] ];
Output: 15

15 is the only lucky number since it is the minimum in its row
and the maximum in its column.
Example 2
Input: $matrix = [ [ 1, 10,  4,  2],
                   [ 9,  3,  8,  7],
                   [15, 16, 17, 12] ];
Output: 12
Example 3
Input: $matrix = [ [7 ,8],
                   [1 ,2] ];
Output: 7

I use pdl to manage the matrix. It has the functions maxover and minover to find the maximum and minimum values over a row. It also has mv to convert rows into columns and viceversa. It has dummy to convert vectors into matrices. Finally it provides which to find out which elements satisfy a given condition. This allows a very compact solution.

Examples:

perl -MPDL -E 'while(@ARGV){$x=pdl(shift);
say "$x -> ",$x->where(($x==$x->minover->dummy(0))&($x==$x->mv(1,0)->maxover->dummy(1)))}
' "[[3 7 8],[9 11 13],[15 16 17]]" "[[1 10 4 2],[9 3 8 7],[15 16 17 12]]" "[[7 8],[1 2]]"

Results:

[
 [ 3  7  8]
 [ 9 11 13]
 [15 16 17]
]
 -> [15]

[
 [ 1 10  4  2]
 [ 9  3  8  7]
 [15 16 17 12]
]
 -> [12]

[
 [7 8]
 [1 2]
]
 -> [7]

This returns an empty ndarray when no lucky number is found.

perl -MPDL -E 'while(@ARGV){$x=pdl(shift);
say "$x -> ",$x->where(($x==$x->minover->dummy(0))&($x==$x->mv(1,0)->maxover->dummy(1)))}
' "[[1 3],[4 2]]"

Results:

[
 [1 3]
 [4 2]
]
 -> Empty[0]

The full code adds checks and tests for empty results:

 1  # Perl weekly challenge 251
 2  # Task 2:  Lucky Numbers
 3  #
 4  # See https://wlmb.github.io/2024/01/08/PWC251/#task-2-lucky-numbers
 5  use v5.36;
 6  use PDL;
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 A1 [A2...]
 9      to find lucky numbers in the arrays A1, A2...
10      The format of the arrays should be "[[a00 a01...],[a10 a11...],...]",
11      to be read by pdl.
12      FIN
13  while(@ARGV){
14      my $in=pdl(shift);
15      my $min=$in->minover->dummy(0);
16      my $max=$in->mv(1,0)->maxover->dummy(1);
17      my $result=$in->where(($in==$min)&($in==$max));
18      say "$in -> ", $result->isempty?-1:$result;
19  }

Examples:

./ch-2.pl "[[3 7 8],[9 11 13],[15 16 17]]" "[[1 10 4 2],[9 3 8 7],[15 16 17 12]]"\
	  "[[7 8],[1 2]]" "[[1 3],[4 2]]"

Results:

[
 [ 3  7  8]
 [ 9 11 13]
 [15 16 17]
]
 -> [15]

[
 [ 1 10  4  2]
 [ 9  3  8  7]
 [15 16 17 12]
]
 -> [12]

[
 [7 8]
 [1 2]
]
 -> [7]

[
 [1 3]
 [4 2]
]
 -> -1

/;

Written on January 8, 2024