Perl Weekly Challenge: Week 198

Challenge 1:

Max Gap

You are given a list of integers, @list.

Write a script to find the total pairs in the sorted list where 2 consecutive elements has the max gap. If the list contains less then 2 elements then return 0.

Example 1
Input:  @list = (2,5,8,1)
Output: 2

Since the sorted list (1,2,5,8) has 2 such pairs (2,5) and (5,8)
Example 2
Input: @list = (3)
Output: 0

The first thing to do is to get @list from the command line arguments and sort it so the elements are in ascending numeric order.

my @list = @args.sort({$^a <=> $^b});

The last stipulation in the spec is easy to implement. If @list has less than two elements, we print 0 and are done.

if @list.elems < 2 {
    say 0;
} else {

If there are two or more, we have more work to do. We need to know what is the maximum gap between pairs of consecutive elements in @list and how many pairs have that length. I chose to express this as a hash called %gaps where the keys are gap lengths and the values are lists of pairs having that gap length.

    my %gaps;

We go through @list starting from the second element and comparing it to the one before until we reach the end. Because @list is sorted numerically, we will never have a negative gap length. As each pair is compared, it is added to the appropriate key in %gaps for its gap length.

    for 1 .. @list.end -> $i {
        %gaps{(@list[$i] - @list[$i - 1])}.push([@list[$i - 1], @list[$i]]);
    }

Once that is complete, we sort gaps in terms of gap length. The first element will be the one with the maximum gap length. We count how many pairs under that key and print the answer.

    %gaps.sort({ $^b.value.elems <=> $^a.value.elems }).first.value.elems.say;
}

(Full code on Github.)

This is the Perl version.

my @list = sort {$a <=> $b} @ARGV;

if (scalar @list < 2) {
    say 0;
} else {
    my %gaps;

    for my $i (1 .. scalar @list - 1) {
        push @{$gaps{($list[$i] - $list[$i - 1])}}, [$list[$i - 1], $list[$i]];
    }

    say scalar @{ $gaps{(sort { $gaps{$b} <=> $gaps{$a} } keys %gaps)[0]} };
}

(Full code on Github.)

Challenge 2:

Prime Count

You are given an integer $n > 0.

Write a script to print the count of primes less than $n.

Example 1
Input: $n = 10
Output: 4 as in there are 4 primes less than 10 are 2, 3, 5 ,7.
Example 2
Input: $n = 15
Output: 6
Example 3
Input: $n = 1
Output: 0
Example 4
Input: $n = 25
Output: 9

This can be solved in Raku as a one-liner. First we fetch the first command line argument and store it in $n. Then we make a range from 0 to $n and .grep() primes from it with .is-prime(). We count how many primes we found with .elems() and print the answer with .say().

my $n = @*ARGS[0]; (0 .. $n).grep({ .is-prime }).elems.say

(Full code on Github.)

The Perl version is not quite so short because we have to provide our own isPrime() function. Luckily I have already written one which I have used in many previous challenges. Now the heart of the script can also be expressed as one line:

say scalar grep { isPrime($_) } 0 .. $n;

(Full code on Github.)