Perl Weekly Challenge 198.

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

Task 1: Max Gap

Submitted by: Mohammad S Anwar
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

I sort the input, build an array of gaps, find the maximum and count how many gaps coincide with it. This fits a one liner:

perl -MList::Util=max -E '
@l=sort {$a<=>$b} @ARGV; $m=max @g=map{$l[$_]-$l[$_-1]} 1..@l-1; say 0+grep{$_==$m} @g;
' 2 5 8 1
perl -MList::Util=max -E '
@l=sort {$a<=>$b} @ARGV; $m=max @g=map{$l[$_]-$l[$_-1]} 1..@l-1; say 0+grep{$_==$m} @g;
' 3

Results:

2
0

The disadvantage of this procedure is that I go twice through the array of gaps, once to find the maximum and once to count how many gaps are equal to it. I can avoid one pass by storing the counts in a hash. I can also calculate the maximum on the fly.

perl -E '@l=sort {$a<=>$b} @ARGV;  for(1..@l-1){++$c{$g=$l[$_]-$l[$_-1]}; $m=$g if $g>$m}; say $c{$m}||0;' 2 5 8 1
perl -E '@l=sort {$a<=>$b} @ARGV;  for(1..@l-1){++$c{$g=$l[$_]-$l[$_-1]}; $m=$g if $g>$m}; say $c{$m}||0;' 3

Results:

2
0

The full code is

 1  # Perl weekly challenge 198
 2  # Task 1:  Max Gap
 3  #
 4  # See https://wlmb.github.io/2023/01/02/PWC198/#task-1-max-gap
 5  use v5.36;
 6  my @sorted=sort {$a<=>$b} @ARGV;
 7  my %count;
 8  my $max;
 9  for(1..@sorted-1){
10      ++$count{my $gap=$sorted[$_]-$sorted[$_-1]};
11      $max=$gap if !defined $max || $gap>$max;
12  };
13  say join " ", @ARGV, "->", $count{$max}||0

Examples:

./ch-1.pl 2 5 8 1
./ch-1.pl 3

Results:

2 5 8 1 -> 2
3 -> 0

Task 2: Prime Count

Submitted by: Mohammad S Anwar
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

I could calculate the number of primes below a certain number by building an Eratosthenes sieve and counting how many elements survive. This is easily done using the Perl Data language:

perl -MPDL -MPDL::NiceSlice -E 'for(@ARGV){say("1 -> 0"), next unless $_>=2; $s=ones($_); $s(0:1).=0;
$s($_**2:-1:$_).=0 for(2..sqrt($_-1)); say "$_ -> ", $s->sumover}' 10 15 1 25

Results:

10 -> 4
15 -> 6
1 -> 0
25 -> 9

Notice that the cases $n=1 (or less) require special treatment to avoid indexing problems.

An alternative is to just use Math::Prime::Util. There is a subtlety as $n may itself be prime, and the challenge statement uses less, not less than. Thus, I have to subtract 1 before calling prime_count.

perl -MMath::Prime::Util=prime_count -E 'say "$_ -> ", prime_count($_-1) for @ARGV' 10 15 1 25

Results:

10 -> 4
15 -> 6
1 -> 0
25 -> 9

The full code is as simple

 1  # Perl weekly challenge 198
 2  # Task 2:  Prime Count
 3  #
 4  # See https://wlmb.github.io/2023/01/02/PWC198/#task-2-prime-count
 5  use v5.36;
 6  use Math::Prime::Util qw(prime_count);
 7  say(<<~"FIN"), exit unless @ARGV;
 8      Usage: $0 N1 [N2...]
 9      to fin the number of primes below N1, N2...
10      FIN
11  say "$_ -> ", prime_count($_-1) for @ARGV;

Example:

./ch-2.pl 10 15 1 25

Results:

10 -> 4
15 -> 6
1 -> 0
25 -> 9
Written on January 2, 2023