Prime the Gap
with Raku

by Arne Sommer

Prime the Gap with Raku

[218] Published 3. January 2023 (and updated 4. January)

This is my response to The Weekly Challenge #198.

Challenge #198.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

File: max-gap
#! /usr/bin/env raku

unit sub MAIN (*@list where @list.elems > 0 && all(@list) ~~ /^<[0..9]>*$/,
      :v(:$verbose));                   # [1]

my @sorted = @list.sort;                # [2]
my @gap;                                # [3]

say ":Sorted: @sorted[]" if $verbose;

my $first = @sorted.shift;              # [4]

while (@sorted)                         # [5]
{
  my $second = @sorted.shift;           # [6]
  my $gap    = $second - $first;        # [7]
  @gap.push: $gap;                      # [8]
  say ":Pair: ($first $second) Gap: $gap" if $verbose;
  $first     = $second;                 # [9]
}

my $max = @gap.max;                     # [10]
my @max = @gap.grep( * == $max );       # [11]

say ":Max Gap: $max" if $verbose;

say @max.elems;                         # [12]

[1] A list (at leart one element, if that can be considered a list) of non-negative integers.

[2] Sort them (with sort); the lowest value first.

See docs.raku.org/routine/sort for more information about sort.

[3] The gaps (the width) will end up here.

[4] Get the first value.

[5] As long as there are more values.

[6] Get the next one.

[7] Compute the gap (distance between the two values).

[8] Save the gap.

[9] Move along the second value, ready for the next iteration (if any).

[10] Get the highest value with max.

See docs.raku.org/routine/max for more information about max.

[11] Get all the entries with this maximum value.

[12] And finally, print the number of (count) those values.

Running it:

$ ./max-gap 2 5 8 1
2

$ ./max-gap 3
0

Ok.

Verbose mode gives us all the pairs, and their gaps:

$ ./max-gap -v 2 5 8 1
:Sorted: 1 2 5 8
:Pair: (1 2) Gap: 1
:Pair: (2 5) Gap: 3
:Pair: (5 8) Gap: 3
:Max Gap: 3
2

$ ./max-gap -v 3
:Max Gap: -Inf
0

-Inf may look funny, but is the result of applying max on nothing (i.e. an empty list). The reason is that if we were to compare this -Inf value with a real one (as in integer, e.g. -100000000), the last one will be higher.

Update 4. January 2023

I wrote this version using map on the indices after a discussion on Redit.

File: max-gap-map
#! /usr/bin/env raku

unit sub MAIN (*@list where @list.elems > 0 && all(@list) ~~ /^<[0..9]>*$/);

my @sorted = @list.sort;
my @gap    = (1 .. @sorted.end).map({ @sorted[$_] - @sorted[$_ -1] });
my @max    = @gap.grep( * == @gap.max );

say @max.elems;

It is included in the zip file, as of 4 January 22:40 UTC.

Challenge #198.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
File: prime-count
#! /usr/bin/env raku

unit sub MAIN (Int $n where $n > 0, :v(:$verbose));  # [1]

my @primes = (1 .. $n -1).grep( *.is-prime );        # [2]

say ":Primes: @primes[]" if $verbose;

say @primes.elems;                                   # [3]

[1] Ensure a positive integer value.

[2] Get the primes upto $n (but not including). We start with all the possible integers, and apply is-prime inside a grep to get rid of non-primes.

See docs.raku.org/routine/is-prime for more information about is-prime.

[3] Print the number of primes.

Running it:

$ ./prime-count 4
2

$ ./prime-count 15
6

$ ./prime-count 1
0

$ ./prime-count 25
9

Looking good.

With verbose mode, just to be sure:

$ ./prime-count -v 4
:Primes: 2 3
2

$ ./prime-count -v 15
:Primes: 2 3 5 7 11 13
6

$ ./prime-count -v 1
:Primes: 
0

$ ./prime-count -v 25
:Primes: 2 3 5 7 11 13 17 19 23
9

The number 7 is a prime number, but is not included when we set is at the upper (upto) limit:

$ ./prime-count -v 7
:Primes: 2 3 5
3

And that's it.