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