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