user
Definitions

The following definitions are needed for this task.

A **tetraprime** is a positive integer which is the product of four distinct primes. For example, 1155 is a tetraprime because 1155 = 3 x 5 x 7 x 11.

The **neighboring pairs** of a prime are the two consecutive numbers immediately preceding or immediately following that prime. For example, (5, 6) and (8, 9) are the neighboring pairs of the prime 7.

Task

1. Find and show here all primes less than **100,000** whose **preceding** neighboring pair are both tetraprimes.

2. Find and show here all primes less than **100,000** whose **following** neighboring pair are both tetraprimes.

3. Of the primes in 1 and 2 above how many have a neighboring pair one of whose members has a prime factor of 7?

4. For the primes in 1 and 2 above, consider the gaps between consecutive primes. What are the minimum, median and maximum gaps?

5. Repeat these calculations for all primes less than **1 million** but for 1 and 2 just show the number of primes - don't print them out individually.

If it is difficult for your language to meet all of these requirements, then just do what you reasonably can.

Stretch

Repeat the calculations for all primes less than **10 million**.

References

* OEIS sequence A361796: Prime numbers preceded by two consecutive numbers which are products of four distinct primes (or tetraprimes).
* OEIS sequence A362578: Prime numbers followed by two consecutive numbers which are products of four distinct primes (or tetraprimes).
assistant
**Translation of**: Wren

```
# 20230721 Raku programming solution

my @primes = (2..1e7).grep: *.is-prime; # cannot do lazy here 

sub median { # based on https://rosettacode.org/wiki/Averages/Median#Raku
   return { ( .[(*-1) div 2] + .[* div 2] ) / 2 }(@_) # for already sorted
}

sub isTetraPrime ($n is copy) { # is cached {
   my ($count,$prevFact) = 0, 1;
   for @primes -> \p {
      my $limit = p * p;
      if $count == 0 {
         $limit = $limit * $limit
      } elsif $count == 1 {
         $limit *= p
      }
      if $limit <= $n {
         while $n %% p {
            return False if ( $count == 4 or p == $prevFact );
            $count++;
            $n div= p;
            $prevFact = p
         }
      } else {
         last      
      }
   }
   if $n > 1 {
      return False if ( $count == 4 or $n == $prevFact );
      $count++
   }
   return $count == 4
}

my ( $j, @tetras1, @tetras2, $sevens1, $sevens2 ) = 1e5;

my \highest7 = @primes.[*-1];
my \highest6 = @primes.first: * < 1e6, :end;
my \highest5 = @primes.first: * < 1e5, :end; 

for @primes -> \p {
   if isTetraPrime p-1 and isTetraPrime p-2 {
      @tetras1.push: p;
      $sevens1++ if ( (p-1) %% 7 or (p-2) %% 7 );
   }
   if isTetraPrime p+1 and isTetraPrime p+2 {
      @tetras2.push: p;
      $sevens2++ if ( (p+1) %% 7 or (p+2) %% 7 ); 
   }
   if p == highest5 | highest6 | highest7 {
      for 0,1 -> \i {
         my (\sevens, \t, @tetras) := i == 0 
            ?? ( $sevens1, "preceding", @tetras1 )
            !! ( $sevens2, "following", @tetras2 ); 
         my \c = @tetras.elems;

         say "Found {c} primes under $j whose {t} neighboring pair are tetraprimes:";
         if p == highest5 {
            say [~] $_>>.fmt('%6s') for @tetras.rotor(10,:partial);       
         }
         say "of which {sevens} have a neighboring pair one of whose factors is 7.\n";
         my \gaps = ( @tetras.rotor(2=>-1).map: { .[1] - .[0] } ).sort;
         
         my (\Min,\Max,\Med) = gaps[0], gaps[*-1], median(gaps);
         say "Minimum gap between those {c} primes : {Min}";
         say "Median  gap between those {c} primes : {Med}";
         say "Maximum gap between those {c} primes : {Max}"; 
         say()
      }
      $j *= 10
   } 
}

```

Output:

Same as Wren