# Factorial primes

Factorial primes
You are encouraged to solve this task according to the task description, using any language you may know.
Definition

A factorial prime is a prime number that is one less or one more than a factorial.

In other words a non-negative integer n corresponds to a factorial prime if either n! - 1 or n! + 1 is prime.

Examples

4 corresponds to the factorial prime 4! - 1 = 23.

5 doesn't correspond to a factorial prime because neither 5! - 1 = 119 (7 x 17) nor 5! + 1 = 121 (11 x 11) are prime.

Find and show here the first 10 factorial primes. As well as the prime itself show the factorial number n to which it corresponds and whether 1 is to be added or subtracted.

As 0! (by convention) and 1! are both 1, ignore the former and start counting from 1!.

Stretch

If your language supports arbitrary sized integers, do the same for at least the next 19 factorial primes.

As it can take a long time to demonstrate that a large number (above say 2^64) is definitely prime, you may instead use a function which shows that a number is probably prime to a reasonable degree of certainty. Most 'big integer' libraries have such a function.

If a number has more than 40 digits, do not show the full number. Show instead the first 20 and the last 20 digits and how many digits in total the number has.

Reference

## ALGOL 68

Basic task. Assumes LONG INT is at least 64 bits.

```BEGIN # find some factorial primes - primes that are f - 1 or f + 1      #
#      for some factorial f                                        #

# is prime PROC based on the one in the primality by trial division task #
PROC is prime = ( LONG INT p )BOOL:
IF p <= 1 OR NOT ODD p THEN
p = 2
ELSE
BOOL prime := TRUE;
FOR i FROM 3 BY 2 TO SHORTEN ENTIER long sqrt(p) WHILE prime := p MOD i /= 0 DO SKIP OD;
prime
FI;
# end of code based on the primality by trial divisio task               #

PROC show factorial prime = ( INT fp number, INT n, CHAR fp op, LONG INT fp )VOID:
print( ( whole( fp number, -2 ), ":", whole( n, -4 )
, "! ", fp op, " 1 = ", whole( fp, 0 )
, newline
)
);
LONG INT f        := 1;
INT      fp count := 0;
FOR n WHILE fp count < 10 DO
f *:= n;
IF  LONG INT fp = f - 1;
is prime( fp )
THEN
show factorial prime( fp count +:= 1, n, "-", fp )
FI;
IF  LONG INT fp = f + 1;
is prime( fp )
THEN
show factorial prime( fp count +:= 1, n, "+", fp )
FI
OD
END```
Output:
``` 1:   1! + 1 = 2
2:   2! + 1 = 3
3:   3! - 1 = 5
4:   3! + 1 = 7
5:   4! - 1 = 23
6:   6! - 1 = 719
7:   7! - 1 = 5039
8:  11! + 1 = 39916801
9:  12! - 1 = 479001599
10:  14! - 1 = 87178291199
```

## C++

```#include <iomanip>
#include <iostream>

#include <gmpxx.h>

using big_int = mpz_class;

std::string to_string(const big_int& num, size_t n) {
std::string str = num.get_str();
size_t len = str.size();
if (len > n) {
str = str.substr(0, n / 2) + "..." + str.substr(len - n / 2);
str += " (";
str += std::to_string(len);
str += " digits)";
}
return str;
}

bool is_probably_prime(const big_int& n) {
return mpz_probab_prime_p(n.get_mpz_t(), 25) != 0;
}

int main() {
big_int f = 1;
for (int i = 0, n = 1; i < 31; ++n) {
f *= n;
if (is_probably_prime(f - 1)) {
++i;
std::cout << std::setw(2) << i << ": " << std::setw(3) << n
<< "! - 1 = " << to_string(f - 1, 40) << '\n';
}
if (is_probably_prime(f + 1)) {
++i;
std::cout << std::setw(2) << i << ": " << std::setw(3) << n
<< "! + 1 = " << to_string(f + 1, 40) << '\n';
}
}
}
```
Output:
``` 1:   1! + 1 = 2
2:   2! + 1 = 3
3:   3! - 1 = 5
4:   3! + 1 = 7
5:   4! - 1 = 23
6:   6! - 1 = 719
7:   7! - 1 = 5039
8:  11! + 1 = 39916801
9:  12! - 1 = 479001599
10:  14! - 1 = 87178291199
11:  27! + 1 = 10888869450418352160768000001
12:  30! - 1 = 265252859812191058636308479999999
13:  32! - 1 = 263130836933693530167218012159999999
14:  33! - 1 = 8683317618811886495518194401279999999
15:  37! + 1 = 13763753091226345046...79581580902400000001 (44 digits)
16:  38! - 1 = 52302261746660111176...24100074291199999999 (45 digits)
17:  41! + 1 = 33452526613163807108...40751665152000000001 (50 digits)
18:  73! + 1 = 44701154615126843408...03680000000000000001 (106 digits)
19:  77! + 1 = 14518309202828586963...48000000000000000001 (114 digits)
20:  94! - 1 = 10873661566567430802...99999999999999999999 (147 digits)
21: 116! + 1 = 33931086844518982011...00000000000000000001 (191 digits)
22: 154! + 1 = 30897696138473508879...00000000000000000001 (272 digits)
23: 166! - 1 = 90036917057784373664...99999999999999999999 (298 digits)
24: 320! + 1 = 21161033472192524829...00000000000000000001 (665 digits)
25: 324! - 1 = 22889974601791023211...99999999999999999999 (675 digits)
26: 340! + 1 = 51008644721037110809...00000000000000000001 (715 digits)
27: 379! - 1 = 24840307460964707050...99999999999999999999 (815 digits)
28: 399! + 1 = 16008630711655973815...00000000000000000001 (867 digits)
29: 427! + 1 = 29063471769607348411...00000000000000000001 (940 digits)
30: 469! - 1 = 67718096668149510900...99999999999999999999 (1051 digits)
31: 546! - 1 = 14130200926141832545...99999999999999999999 (1260 digits)
```

## F#

```// Factorial primes. Nigel Galloway: August 15th., 2022
let fN g=if Open.Numeric.Primes.MillerRabin.IsProbablePrime &g then Some(g) else None
let fp()=let rec fG n g=seq{let n=n*g in yield (fN(n-1I),-1,g); yield (fN(n+1I),1,g); yield! fG n (g+1I)} in fG 1I 1I|>Seq.filter(fun(n,_,_)->Option.isSome n)
fp()|>Seq.iteri(fun i (n,g,l)->printfn \$"""%2d{i+1}: %3d{int l}!%+d{g} -> %s{let n=string(Option.get n) in if n.Length<41 then n else n[0..19]+".."+n[n.Length-20..]+" ["+string(n.Length)+" digits]"}""")
```
Output:
``` 1:   1!+1 -> 2
2:   2!+1 -> 3
3:   3!-1 -> 5
4:   3!+1 -> 7
5:   4!-1 -> 23
6:   6!-1 -> 719
7:   7!-1 -> 5039
8:  11!+1 -> 39916801
9:  12!-1 -> 479001599
10:  14!-1 -> 87178291199
11:  27!+1 -> 10888869450418352160768000001
12:  30!-1 -> 265252859812191058636308479999999
13:  32!-1 -> 263130836933693530167218012159999999
14:  33!-1 -> 8683317618811886495518194401279999999
15:  37!+1 -> 13763753091226345046..79581580902400000001 [44 digits]
16:  38!-1 -> 52302261746660111176..24100074291199999999 [45 digits]
17:  41!+1 -> 33452526613163807108..40751665152000000001 [50 digits]
18:  73!+1 -> 44701154615126843408..03680000000000000001 [106 digits]
19:  77!+1 -> 14518309202828586963..48000000000000000001 [114 digits]
20:  94!-1 -> 10873661566567430802..99999999999999999999 [147 digits]
21: 116!+1 -> 33931086844518982011..00000000000000000001 [191 digits]
22: 154!+1 -> 30897696138473508879..00000000000000000001 [272 digits]
23: 166!-1 -> 90036917057784373664..99999999999999999999 [298 digits]
24: 320!+1 -> 21161033472192524829..00000000000000000001 [665 digits]
25: 324!-1 -> 22889974601791023211..99999999999999999999 [675 digits]
26: 340!+1 -> 51008644721037110809..00000000000000000001 [715 digits]
27: 379!-1 -> 24840307460964707050..99999999999999999999 [815 digits]
28: 399!+1 -> 16008630711655973815..00000000000000000001 [867 digits]
29: 427!+1 -> 29063471769607348411..00000000000000000001 [940 digits]
30: 469!-1 -> 67718096668149510900..99999999999999999999 [1051 digits]
31: 546!-1 -> 14130200926141832545..99999999999999999999 [1260 digits]
```

## J

```    (,. (-!)/"1)1>.(,. >.@(!inv)@<:) (#~ 1 p: ]) ~.,(!i.27x)+/1 _1
2  1  1
3  2  1
7  3  1
5  3 _1
23  4 _1
719  6 _1
5039  7 _1
39916801 11  1
479001599 12 _1
87178291199 14 _1
```

(i.28x here would have given us an eleventh prime, but the task asked for the first 10, and the stretch goal requires considerable patience.)

## Java

```public class MainApp {
public static void main(String[] args) {
int countOfPrimes = 0;
final int targetCountOfPrimes = 10;
long f = 1;
while (countOfPrimes < targetCountOfPrimes) {
long factorialNum = getFactorial(f);
boolean primePlus = isPrime(factorialNum + 1);
boolean primeMinus = isPrime(factorialNum - 1);
if (primeMinus) {
countOfPrimes++;
System.out.println(countOfPrimes + ": " + factorialNum + "! - 1 = " + (factorialNum - 1));

}
if (primePlus  && f > 1) {
countOfPrimes++;
System.out.println(countOfPrimes + ": " + factorialNum + "! + 1 = " + (factorialNum + 1));
}
f++;
}
}

private static long getFactorial(long f) {
long factorial = 1;
for (long i = 1; i < f; i++) {
factorial *= i;
}
return factorial;
}

private static boolean isPrime(long num) {
if (num < 2) {return false;}
for (long i = 2; i < num; i++) {
if (num % i == 0) {return false;}
}
return true;
}
}
```

Results

```1: 1! + 1 = 2
2: 2! + 1 = 3
3: 6! - 1 = 5
4: 6! + 1 = 7
5: 24! - 1 = 23
6: 720! - 1 = 719
7: 5040! - 1 = 5039
8: 39916800! + 1 = 39916801
9: 479001600! - 1 = 479001599
10: 87178291200! - 1 = 87178291199
```

### Another Way with BigIntegers

```import java.math.BigInteger;

public class MainApp {
public static void main(String[] args) {
//Used to measure total runtime of program.
long starttime = System.nanoTime();
//How many primes found, how many primes wanted, loop counter.
int countOfPrimes = 0;
final int targetCountOfPrimes = 30;
long f = 1;
//Starting BigInteger at 1.
BigInteger biFactorial = BigInteger.ONE;
while (countOfPrimes < targetCountOfPrimes) {
//Each loop, multiply the number by the loop
//counter (f) to increase factorial much more quickly.
biFactorial = biFactorial.multiply(BigInteger.valueOf(f));
// one less than the factorial.
BigInteger biMinusOne = biFactorial.subtract(BigInteger.ONE);
// one more than the factorial.

//Determine if the numbers are prime with a probability of 100
boolean primeMinus = biMinusOne.isProbablePrime(100);
boolean primePlus = biPlusOne.isProbablePrime(100);

//Make the big number look like a pretty string for output.
String biMinusOneString = convert(biMinusOne);
String biPlusOneString = convert(biPlusOne);

//If the number was prime, output and increment the primt counter.
if (primeMinus) {
countOfPrimes++;
System.out.println(
countOfPrimes + ": " + f + "! - 1 = " + biMinusOneString);
}
if (primePlus) {
countOfPrimes++;
System.out.println(countOfPrimes + ": " + f + "! + 1 = " + biPlusOneString);
}
//Increment loop counter.
f++;
}
//Calculate and display program runtime.
long stoptime = System.nanoTime();
long runtime = stoptime - starttime;
System.out.println("Program runtime: " + runtime + " ns (~" + runtime/1_000_000_000 + " seconds)");
}

//Method to make output pretty
private static String convert(BigInteger bi) {
String s = bi.toString();
int l = s.length();
String s2 = "";
if (l >= 40) {
s2 = s.substring(0, 19);
s2 += "..." + s.substring(s.length() - 20, s.length());
s2 += " : " + l + " digits";
} else {s2 = s;}
return s2;
}
}
```

### output

```1: 1! + 1 = 2
2: 2! + 1 = 3
3: 3! - 1 = 5
4: 3! + 1 = 7
5: 4! - 1 = 23
6: 6! - 1 = 719
7: 7! - 1 = 5039
8: 11! + 1 = 39916801
9: 12! - 1 = 479001599
10: 14! - 1 = 87178291199
11: 27! + 1 = 10888869450418352160768000001
12: 30! - 1 = 265252859812191058636308479999999
13: 32! - 1 = 263130836933693530167218012159999999
14: 33! - 1 = 8683317618811886495518194401279999999
15: 37! + 1 = 1376375309122634504...79581580902400000001 : 44 digits
16: 38! - 1 = 5230226174666011117...24100074291199999999 : 45 digits
17: 41! + 1 = 3345252661316380710...40751665152000000001 : 50 digits
18: 73! + 1 = 4470115461512684340...03680000000000000001 : 106 digits
19: 77! + 1 = 1451830920282858696...48000000000000000001 : 114 digits
20: 94! - 1 = 1087366156656743080...99999999999999999999 : 147 digits
21: 116! + 1 = 3393108684451898201...00000000000000000001 : 191 digits
22: 154! + 1 = 3089769613847350887...00000000000000000001 : 272 digits
23: 166! - 1 = 9003691705778437366...99999999999999999999 : 298 digits
24: 320! + 1 = 2116103347219252482...00000000000000000001 : 665 digits
25: 324! - 1 = 2288997460179102321...99999999999999999999 : 675 digits
26: 340! + 1 = 5100864472103711080...00000000000000000001 : 715 digits
27: 379! - 1 = 2484030746096470705...99999999999999999999 : 815 digits
28: 399! + 1 = 1600863071165597381...00000000000000000001 : 867 digits
29: 427! + 1 = 2906347176960734841...00000000000000000001 : 940 digits
30: 469! - 1 = 6771809666814951090...99999999999999999999 : 1051 digits
Program runtime: 6084297200 ns (~6 seconds)
```

## jq

The following jq program has been tested with both the C and Go implementations of jq. The latter supports unbounded-precision arithmetic, but the former has sufficient accuracy to compute the first 10 factorial primes. However, the implementation of `is_prime` used here is not sufficiently fast to compute more than the first 10 factorial primes in a reasonable amount of time.

```# The algorithm is quite fast because the state of `until` is just a number and we skip by 2 or 4
def is_prime:
. as \$n
| if (\$n < 2)         then false
elif (\$n % 2 == 0)  then \$n == 2
elif (\$n % 3 == 0)  then \$n == 3
else 5
| until( . <= 0;
if .*. > \$n then -1
elif (\$n % . == 0) then 0
else . + 2
|  if (\$n % . == 0) then 0
else . + 4
end
end)
| . == -1
end;

def factorial_primes:
foreach range(1; infinite) as \$i (1; . * \$i;
if ((.-1) | is_prime) then [(\$i|tostring) + "! - 1 = ", .-1] else empty end,
if ((.+1) | is_prime) then [(\$i|tostring) + "! + 1 = ", .+1] else empty end ) ;

limit(20; factorial_primes)
| .[1] |= (tostring | (if length > 40 then .[:20] + " .. " + .[-20:] else . end))

Invocation: jq -nr -f factorial-primes.jq

Output:
```1! + 1 = 2
2! + 1 = 3
3! - 1 = 5
3! + 1 = 7
4! - 1 = 23
6! - 1 = 719
7! - 1 = 5039
11! + 1 = 39916801
12! - 1 = 479001599
14! - 1 = 87178291199
# terminated
```

## Julia

```using Primes

limitedprint(n) = (s = string(n); n = length(s); return n <= 40 ? s : s[1:20] * "..." * s[end-19:end] * " (\$n digits)")

function showfactorialprimes(N)
for i in big"1":N
f = factorial(i)
isprime(f - 1) && println(lpad(i, 3), "! - 1 -> ", limitedprint(f - 1))
isprime(f + 1) && println(lpad(i, 3), "! + 1 -> ", limitedprint(f + 1))
end
end

showfactorialprimes(1000)
```
Output:
```  1! + 1 -> 2
2! + 1 -> 3
3! - 1 -> 5
3! + 1 -> 7
4! - 1 -> 23
6! - 1 -> 719
7! - 1 -> 5039
11! + 1 -> 39916801
12! - 1 -> 479001599
14! - 1 -> 87178291199
27! + 1 -> 10888869450418352160768000001
30! - 1 -> 265252859812191058636308479999999
32! - 1 -> 263130836933693530167218012159999999
33! - 1 -> 8683317618811886495518194401279999999
37! + 1 -> 13763753091226345046...79581580902400000001 (44 digits)
38! - 1 -> 52302261746660111176...24100074291199999999 (45 digits)
41! + 1 -> 33452526613163807108...40751665152000000001 (50 digits)
73! + 1 -> 44701154615126843408...03680000000000000001 (106 digits)
77! + 1 -> 14518309202828586963...48000000000000000001 (114 digits)
94! - 1 -> 10873661566567430802...99999999999999999999 (147 digits)
116! + 1 -> 33931086844518982011...00000000000000000001 (191 digits)
154! + 1 -> 30897696138473508879...00000000000000000001 (272 digits)
166! - 1 -> 90036917057784373664...99999999999999999999 (298 digits)
320! + 1 -> 21161033472192524829...00000000000000000001 (665 digits)
324! - 1 -> 22889974601791023211...99999999999999999999 (675 digits)
340! + 1 -> 51008644721037110809...00000000000000000001 (715 digits)
379! - 1 -> 24840307460964707050...99999999999999999999 (815 digits)
399! + 1 -> 16008630711655973815...00000000000000000001 (867 digits)
427! + 1 -> 29063471769607348411...00000000000000000001 (940 digits)
469! - 1 -> 67718096668149510900...99999999999999999999 (1051 digits)
546! - 1 -> 14130200926141832545...99999999999999999999 (1260 digits)
872! + 1 -> 19723152008295244962...00000000000000000001 (2188 digits)
974! - 1 -> 55847687633820181096...99999999999999999999 (2490 digits)
```

## LOLCODE

Basic task, based on the Algol 68 sample.

```OBTW find some factorial primes - primes that are f - 1 or f + 1
for some factorial f
TLDR

HAI 1.3

HOW IZ I TESTIN YR P    BTW PRIMALITY TEST WITH TRIAL DIVISHUN
DIFFRINT 3 AN SMALLR OF 3 AN P, O RLY?
YA RLY
FOUND YR BOTH SAEM P AN 2
MEBBE BOTH SAEM 0 AN MOD OF P AN 2
FOUND YR FAIL
NO WAI
I HAS A IZPRIME ITZ WIN
I HAS A N ITZ 3
I HAS A NSKWARED ITZ 9
IM IN YR PRIMELOOP UPPIN YR I TIL DIFFRINT NSKWARED AN SMALLR OF P AN NSKWARED
DIFFRINT 0 AN MOD OF P AN N, O RLY?
YA RLY
N R SUM OF N AN 2
NSKWARED R PRODUKT OF N AN N
NO WAI
IZPRIME R FAIL
NSKWARED R SUM OF P AN 1
OIC
IM OUTTA YR PRIMELOOP
FOUND YR IZPRIME
OIC
IF U SAY SO

HOW IZ I PADDIN YR FPNUMBR
I HAS A PAD ITZ ""
BOTH SAEM FPNUMBR AN SMALLR OF FPNUMBR AN 9, O RLY?
YA RLY
OIC
FOUND YR SMOOSH PAD AN FPNUMBR MKAY
IF U SAY SO

HOW IZ I SHOWIN YR FPNUMBR AN YR N AN YR HOWDIFF AN YR FP
VISIBLE SMOOSH I IZ PADDIN YR FPNUMBR MKAY ...
AN ":: " AN I IZ PADDIN YR N MKAY ...
AN "! " AN HOWDIFF AN " 1 = " AN FP ...
MKAY
IF U SAY SO

I HAS A F ITZ 1
I HAS A N ITZ 0
I HAS A KOWNT ITZ 0
IM IN YR FPLOOP UPPIN YR I TIL BOTH SAEM KOWNT AN 10
N R SUM OF N AN 1
F R PRODUKT OF F AN N
I IZ TESTIN YR DIFF OF F AN 1 MKAY, O RLY?
YA RLY
KOWNT R SUM OF KOWNT AN 1
I IZ SHOWIN YR KOWNT AN YR N AN YR "-" AN YR DIFF OF F AN 1 MKAY
OIC
I IZ TESTIN YR SUM OF F AN 1 MKAY, O RLY?
YA RLY
KOWNT R SUM OF KOWNT AN 1
I IZ SHOWIN YR KOWNT AN YR N AN YR "+" AN YR SUM OF F AN 1 MKAY
OIC
IM OUTTA YR FPLOOP

KTHXBYE```
Output:
``` 1:  1! + 1 = 2
2:  2! + 1 = 3
3:  3! - 1 = 5
4:  3! + 1 = 7
5:  4! - 1 = 23
6:  6! - 1 = 719
7:  7! - 1 = 5039
8: 11! + 1 = 39916801
9: 12! - 1 = 479001599
10: 14! - 1 = 87178291199
```

## OCaml

```let is_prime (_, n, _) =
let rec test x =
let d = n / x in x > d || x * d <> n && n mod (x + 2) <> 0 && test (x + 6)
in
if n < 5
then n lor 1 = 3
else n land 1 <> 0 && n mod 3 <> 0 && test 5

let factorials_plus_minus_one =
let rec next x y () =
Seq.Cons ((x, pred y, 0), Seq.cons (x, succ y, 1) (next (succ x) (succ x * y)))
in
next 1 1

let () =
let show (x, y, a) = Printf.printf "%3u! %c 1 = %u\n" x [|'-'; '+'|].(a) y in
factorials_plus_minus_one |> Seq.filter is_prime |> Seq.take 10 |> Seq.iter show
```
Output:
```  1! + 1 = 2
2! + 1 = 3
3! - 1 = 5
3! + 1 = 7
4! - 1 = 23
6! - 1 = 719
7! - 1 = 5039
11! + 1 = 39916801
12! - 1 = 479001599
14! - 1 = 87178291199
```

## Perl

Library: ntheory
```use v5.36;
use ntheory <is_prime factorial>;

sub show (\$d) { my \$l = length \$d; \$l < 41 ? \$d : substr(\$d,0,20) . '..' . substr(\$d,-20) . " (\$l digits)" }

my(\$cnt,\$n);
my \$fmt = "%2d: %3d! %s 1 = %s\n";

while () {
my \$f = factorial ++\$n;
if (is_prime \$f-1) { printf \$fmt, ++\$cnt, \$n, '-', show \$f-1 }
if (is_prime \$f+1) { printf \$fmt, ++\$cnt, \$n, '+', show \$f+1 }
last if \$cnt == 30;
}
```
Output:
``` 1:   1! + 1 = 2
2:   2! + 1 = 3
3:   3! - 1 = 5
4:   3! + 1 = 7
5:   4! - 1 = 23
6:   6! - 1 = 719
7:   7! - 1 = 5039
8:  11! + 1 = 39916801
9:  12! - 1 = 479001599
10:  14! - 1 = 87178291199
11:  27! + 1 = 10888869450418352160768000001
12:  30! - 1 = 265252859812191058636308479999999
13:  32! - 1 = 263130836933693530167218012159999999
14:  33! - 1 = 8683317618811886495518194401279999999
15:  37! + 1 = 13763753091226345046..79581580902400000001 (44 digits)
16:  38! - 1 = 52302261746660111176..24100074291199999999 (45 digits)
17:  41! + 1 = 33452526613163807108..40751665152000000001 (50 digits)
18:  73! + 1 = 44701154615126843408..03680000000000000001 (106 digits)
19:  77! + 1 = 14518309202828586963..48000000000000000001 (114 digits)
20:  94! - 1 = 10873661566567430802..99999999999999999999 (147 digits)
21: 116! + 1 = 33931086844518982011..00000000000000000001 (191 digits)
22: 154! + 1 = 30897696138473508879..00000000000000000001 (272 digits)
23: 166! - 1 = 90036917057784373664..99999999999999999999 (298 digits)
24: 320! + 1 = 21161033472192524829..00000000000000000001 (665 digits)
25: 324! - 1 = 22889974601791023211..99999999999999999999 (675 digits)
26: 340! + 1 = 51008644721037110809..00000000000000000001 (715 digits)
27: 379! - 1 = 24840307460964707050..99999999999999999999 (815 digits)
28: 399! + 1 = 16008630711655973815..00000000000000000001 (867 digits)
29: 427! + 1 = 29063471769607348411..00000000000000000001 (940 digits)
30: 469! - 1 = 67718096668149510900..99999999999999999999 (1051 digits)```

## Phix

```with javascript_semantics
include mpfr.e
atom tp = time(), tm = time()+16    -- per, max 16s runtime
mpz {e,f} = mpz_inits(2,1)
integer i = 1, c = 0
while time()<tm do
mpz_mul_si(f,f,i)
for k in {-1,+1} do
if mpz_prime(e) then
c += 1
string s = iff(k<0?"-":"+"),
es = mpz_get_short_str(e),
et = elapsed(time()-tp,0.1," (%s)")
printf(1,"%2d: %3d! %s %d = %s%s\n",{c,i,s,abs(k),es,et})
tp = time()
end if
end for
i += 1
end while
```
Output:
``` 1:   1! + 1 = 2
2:   2! + 1 = 3
3:   3! - 1 = 5
4:   3! + 1 = 7
5:   4! - 1 = 23
6:   6! - 1 = 719
7:   7! - 1 = 5039
8:  11! + 1 = 39916801
9:  12! - 1 = 479001599
10:  14! - 1 = 87178291199
11:  27! + 1 = 10888869450418352160768000001
12:  30! - 1 = 265252859812191058636308479999999
13:  32! - 1 = 263130836933693530167218012159999999
14:  33! - 1 = 8683317618811886495518194401279999999
15:  37! + 1 = 13763753091226345046315979581580902400000001
16:  38! - 1 = 523022617466601111760007224100074291199999999
17:  41! + 1 = 33452526613163807108170062053440751665152000000001
18:  73! + 1 = 44701154615126843408...03680000000000000001 (106 digits)
19:  77! + 1 = 14518309202828586963...48000000000000000001 (114 digits)
20:  94! - 1 = 10873661566567430802...99999999999999999999 (147 digits)
21: 116! + 1 = 33931086844518982011...00000000000000000001 (191 digits)
22: 154! + 1 = 30897696138473508879...00000000000000000001 (272 digits)
23: 166! - 1 = 90036917057784373664...99999999999999999999 (298 digits)
24: 320! + 1 = 21161033472192524829...00000000000000000001 (665 digits) (2.5s)
25: 324! - 1 = 22889974601791023211...99999999999999999999 (675 digits) (0.2s)
26: 340! + 1 = 51008644721037110809...00000000000000000001 (715 digits) (0.8s)
27: 379! - 1 = 24840307460964707050...99999999999999999999 (815 digits) (2.0s)
28: 399! + 1 = 16008630711655973815...00000000000000000001 (867 digits) (1.9s)
29: 427! + 1 = 29063471769607348411...00000000000000000001 (940 digits) (3.2s)
30: 469! - 1 = 67718096668149510900...99999999999999999999 (1,051 digits) (5.4s)
```

Items 15-17 are shown in full because that's still shorter than 20+length("...")+20+length(" (NN digits)").
Aside: Unfortunately the relative performance falls off a cliff under pwa/p2js by the 320! mark, and it'd probably need a few minutes to get to the 30th.

## Raku

```sub postfix:<!> (\$n) { constant @F = (1, 1, |[\*] 2..*); @F[\$n] }
sub abr (\$_) { .chars < 41 ?? \$_ !! .substr(0,20) ~ '..' ~ .substr(*-20) ~ " ({.chars} digits)" }

my \$limit;

for 1..* {
my \f = .!;
++\$limit and printf "%2d: %3d! - 1 = %s\n", \$limit, \$_, abr f -1 if (f -1).is-prime;
++\$limit and printf "%2d: %3d! + 1 = %s\n", \$limit, \$_, abr f +1 if (f +1).is-prime;
exit if \$limit >= 30
}
```
Output:
``` 1:   1! + 1 = 2
2:   2! + 1 = 3
3:   3! - 1 = 5
4:   3! + 1 = 7
5:   4! - 1 = 23
6:   6! - 1 = 719
7:   7! - 1 = 5039
8:  11! + 1 = 39916801
9:  12! - 1 = 479001599
10:  14! - 1 = 87178291199
11:  27! + 1 = 10888869450418352160768000001
12:  30! - 1 = 265252859812191058636308479999999
13:  32! - 1 = 263130836933693530167218012159999999
14:  33! - 1 = 8683317618811886495518194401279999999
15:  37! + 1 = 13763753091226345046..79581580902400000001 (44 digits)
16:  38! - 1 = 52302261746660111176..24100074291199999999 (45 digits)
17:  41! + 1 = 33452526613163807108..40751665152000000001 (50 digits)
18:  73! + 1 = 44701154615126843408..03680000000000000001 (106 digits)
19:  77! + 1 = 14518309202828586963..48000000000000000001 (114 digits)
20:  94! - 1 = 10873661566567430802..99999999999999999999 (147 digits)
21: 116! + 1 = 33931086844518982011..00000000000000000001 (191 digits)
22: 154! + 1 = 30897696138473508879..00000000000000000001 (272 digits)
23: 166! - 1 = 90036917057784373664..99999999999999999999 (298 digits)
24: 320! + 1 = 21161033472192524829..00000000000000000001 (665 digits)
25: 324! - 1 = 22889974601791023211..99999999999999999999 (675 digits)
26: 340! + 1 = 51008644721037110809..00000000000000000001 (715 digits)
27: 379! - 1 = 24840307460964707050..99999999999999999999 (815 digits)
28: 399! + 1 = 16008630711655973815..00000000000000000001 (867 digits)
29: 427! + 1 = 29063471769607348411..00000000000000000001 (940 digits)
30: 469! - 1 = 67718096668149510900..99999999999999999999 (1051 digits)```

## Wren

### Basic

Library: Wren-math
Library: Wren-fmt
```import "./math" for Int
import "./fmt" for Fmt

System.print("First 10 factorial primes;")
var c = 0
var i = 1
var f = 1
while (true) {
for (gs in [[f-1, "-"], [f+1, "+"]]) {
if (Int.isPrime(gs[0])) {
Fmt.print("\$2d: \$2d! \$s 1 = \$d", c = c + 1, i, gs[1], gs[0])
if (c == 10) return
}
}
i = i + 1
f = f * i
}
```
Output:
```First 10 factorial primes;
1:  1! + 1 = 2
2:  2! + 1 = 3
3:  3! - 1 = 5
4:  3! + 1 = 7
5:  4! - 1 = 23
6:  6! - 1 = 719
7:  7! - 1 = 5039
8: 11! + 1 = 39916801
9: 12! - 1 = 479001599
10: 14! - 1 = 87178291199
```

### Stretch

Library: Wren-gmp

This takes about 28.5 seconds to reach the 33rd factorial prime on my machine (Core i7) with the last two being noticeably slower to emerge. Likely to be very slow after that as the next factorial prime is 1477! + 1.

```import "./gmp" for Mpz
import "./fmt" for Fmt

var limit = 33
var c = 0
var i = 1
var f = Mpz.one
System.print("First %(limit) factorial primes;")
while (true) {
f.mul(i)
var r = (i < 21) ? 1 : 0  // test for definite primeness below 2^64
for (gs in [[f-1, "-"], [f+1, "+"]]) {
if (gs[0].probPrime(15) > r) {
var s = gs[0].toString
var sc = s.count
var digs = sc > 40 ? "(%(sc) digits)" : ""
Fmt.print("\$2d: \$3d! \$s 1 = \$20a \$s", c = c + 1, i, gs[1], s, digs)
if (c == limit) return
}
}
i = i + 1
}
```
Output:
```First 33 factorial primes;
1:   1! + 1 = 2
2:   2! + 1 = 3
3:   3! - 1 = 5
4:   3! + 1 = 7
5:   4! - 1 = 23
6:   6! - 1 = 719
7:   7! - 1 = 5039
8:  11! + 1 = 39916801
9:  12! - 1 = 479001599
10:  14! - 1 = 87178291199
11:  27! + 1 = 10888869450418352160768000001
12:  30! - 1 = 265252859812191058636308479999999
13:  32! - 1 = 263130836933693530167218012159999999
14:  33! - 1 = 8683317618811886495518194401279999999
15:  37! + 1 = 13763753091226345046...79581580902400000001 (44 digits)
16:  38! - 1 = 52302261746660111176...24100074291199999999 (45 digits)
17:  41! + 1 = 33452526613163807108...40751665152000000001 (50 digits)
18:  73! + 1 = 44701154615126843408...03680000000000000001 (106 digits)
19:  77! + 1 = 14518309202828586963...48000000000000000001 (114 digits)
20:  94! - 1 = 10873661566567430802...99999999999999999999 (147 digits)
21: 116! + 1 = 33931086844518982011...00000000000000000001 (191 digits)
22: 154! + 1 = 30897696138473508879...00000000000000000001 (272 digits)
23: 166! - 1 = 90036917057784373664...99999999999999999999 (298 digits)
24: 320! + 1 = 21161033472192524829...00000000000000000001 (665 digits)
25: 324! - 1 = 22889974601791023211...99999999999999999999 (675 digits)
26: 340! + 1 = 51008644721037110809...00000000000000000001 (715 digits)
27: 379! - 1 = 24840307460964707050...99999999999999999999 (815 digits)
28: 399! + 1 = 16008630711655973815...00000000000000000001 (867 digits)
29: 427! + 1 = 29063471769607348411...00000000000000000001 (940 digits)
30: 469! - 1 = 67718096668149510900...99999999999999999999 (1051 digits)
31: 546! - 1 = 14130200926141832545...99999999999999999999 (1260 digits)
32: 872! + 1 = 19723152008295244962...00000000000000000001 (2188 digits)
33: 974! - 1 = 55847687633820181096...99999999999999999999 (2490 digits)
```

## XPL0

```func IsPrime(N);        \Return 'true' if N is prime
real N;  int  I;
[if N <= 2. then return N = 2.;
if Mod(N, 2.) = 0. then \even\ return false;
for I:= 3 to fix(sqrt(N)) do
[if Mod(N, float(I)) = 0. then return false;
I:= I+1;
];
return true;
];

func real Factorial(N); \Return N!
int N;  real F;
[F:= float(N);
while N > 1 do
[N:= N-1;
F:= F * float(N);
];
return F;
];

int  N, C;  real F;
[N:= 1;  C:= 0;
Format(1, 0);
repeat  F:= Factorial(N);
if IsPrime(F-1.) then
[IntOut(0, N);
Text(0, "! - 1 = ");
RlOut(0, F-1.);
CrLf(0);
C:= C+1;
];
if IsPrime(F+1.) then
[IntOut(0, N);
Text(0, "! + 1 = ");
RlOut(0, F+1.);
CrLf(0);
C:= C+1;
];
N:= N+1;
until   C >= 10;
]```
Output:
```1! + 1 = 2
2! + 1 = 3
3! - 1 = 5
3! + 1 = 7
4! - 1 = 23
6! - 1 = 719
7! - 1 = 5039
11! + 1 = 39916801
12! - 1 = 479001599
14! - 1 = 87178291199
```