# Perl Weekly Challenge 198.

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

``````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  #
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
``````

``````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  #
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