PWC 231

PWC 231

Two easy challenges this week. It is tempting to try them in Perl 5, Raku as well as Julia, but alas, I don't have the time. So here goes Perl 5 only.

Challenge 1 (Min Max)

We are given a list of distinct integers and asked to return the elements that are neither the maximum nor the minimum. If there are no such elements, then return -1. That happens if the list length is 2 or less, in which case every element is perforce either a maximum or minimum or both.

I sort the list and return the elements between the head and the tail. I use PDL.

Here is the key subroutine:

sub min_max {    
    my $ints=pdl(@_)->uniqvec;
    ($ints->dim(0) > 2) ?
        ($ints->qsort->(1:(($ints->dim(0))-2))) :
        (-1);
}

Just in case the input is not a list of distinct integers, I force it to its unique elements using the PDL uniqvec method. I then check if the length is 2 or less, in which case we return -1, else we sort and return the sub-piddle between the head and tail.

Challenge 2 (Senior citizen)

We are given a list of strings where every string is in the format "#########<####" (the first 10 digits representing a phone number, 1 alphanumeric (presumably either 'M' or 'F') denoting sex, and 4 digits, the first two of which represent age, and the last two represent a seat number).

We are asked to count the number of elements that represent an age greater than or equal to 60.

One can use grep to extract and count the strings with ages greater than or equal to 60. Just in case, we can also check that each string is in the correct format using a regex. Here is the subroutine:

sub senior_citizens {
    #
    #-- helper sub sub
    local *validate_input = sub {
        $_[0] =~ m/^\d{10}[MF]{1}\d{4}$/;
    };
    #
    #-- back to trunk of sub
    scalar
    grep
    {
        (&validate_input($_)) &&
        (substr($_,11,2) >= 60);
    }
    @_;
}

A more idiomatic approach would be to avoid the &validate_input sub-subroutine, and directly put the regex into the grep as in:

    scalar grep
    {
        (
m/^\d{10}[MF]{1}\d{4}$/) &&
        (substr($_,11,2) >= 60);
    }
    @_;

I realized while typing that that the two conditions can be combined. We can just check that the 11th position in the regex is a number in [6-9] like:

     scalar grep /^\d{10}[MF]{1}[6-9]{1}\d{3}$/, @_;

I kinda like sub-subroutines though, and it is more readable with one. So I will leave my original code as is. Also the sub-subroutine can easily be extended to throw an exception if invalid input is encountered. That is not so easy with the compact one-liner just above.

Comments

Popular posts from this blog

PWC 258

PWC 253

PWC 251