**Advent Calendar 2023**

### | **Day 9** | **Day 10** | **Day 11** |

The gift is presented by `Stephen G Lynn`

. Today he is talking about his solution to **The Weekly Challenge - 217**. This is re-produced for `Advent Calendar 2023`

from the original **post**.

**Challenge 1 (Sorted Matrix)**

We are given a `n by n`

matrix of numbers, and asked to report the third-smallest number in the matrix.

The specification seems to allow arbitrary non-numeric elements too, but since all the test examples are numeric, I will restrict to numeric matrices. `PDL`

is of course the go-to tool for this.

The core subroutine:

```
sub sorted_matrix {my ($pdl)=@_; $pdl=$pdl->flat->qsort; $pdl(2);}
```

The flat method flattens the matrix piddle to a vector piddle, qsort sorts the vector in ascending order, then we just return the third element.

**Challenge 2 (Max Number)**

We are given a list of positive integers of arbitrary lengths, and asked to concatenate them so as to produce the largest possible concatenated number. Thus, given `1`

and `23`

, we would produce `231`

, not `123`

.

To solve this, we exploit the fact that `Perl`

can treat the elements interchangeably as numbers or as strings. We first sort the numbers using a routine that puts `$b`

before `$a`

if `$b.$a`

is greater than `$a.$b`

. Thus, we would sort `(1,23)`

as `(23,1)`

because `231 > 123`

.

The core snippet:

```
join '', sort { $b.$a <=> $a.$b } @list;
```

A simpler approach suggests itself as just the straight descending lexical `sort {$b cmp $a}`

. But this fails for example with `(1,10)`

, which would be sorted as `10,1`

not the desired `1,10`

.

### The comparison function in sort

Let me briefly explain my own understanding of how comparison functions work in sort. The documentation can be a bit cryptic.

The general syntax of sort is:

```
sort f($a,$b) @list;
```

Here `f($a,$b)`

is the comparison function. A comparison function can return `-1`

, `0`

, or `1`

. Here `$a`

and `$b`

are standard package variables (global variables) that temporarily store two list elements being compared during the sort process.

If `f($a,$b)`

returns `-1`

, `$a`

is placed before `$b`

in the sorted list.

If `f($a,$b)`

returns `1`

, `$a`

is placed after `$b`

in the sorted list.

If `f($a,$b)`

returns `0`

, `$a`

and `$b`

would be tied in the sorted list (in any order in the sorted list but adjacent to each other or to other elements that return `0`

when compared to either of them).

With the spaceship operator `<=>`

: `$x<=>$y`

returns `-1`

if `$x`

is less than `$y`

, `1`

if `$x`

is greater than `$y`

, and `0`

if `$x`

is numerically equal `(==)`

to `$y`

.

So setting `f($a,$b)`

to `$a <=> $b`

will sort in ascending order, while setting `f($a,$b)`

to `$b <=> $a`

will sort in descending order.

With the string comparison operator `cmp`

: `$x cmp $y`

returns `-1`

if `$x`

is before `$y`

in the dictionary `($x lt $y)`

, `1`

if `$x`

is after `$y`

in the dictionary `($x gt $y)`

, and `0`

if the value of `$x`

is the same string as the value of `$y`

($x eq $y).

We could rewrite the core snippet above as follows to make the logic more clear:

```
sub f {my ($x,$y)=@_; $y.$x <=> $x.$y}
join '', sort &f($a,$b) @list;
```

If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.