Factorial primes

From Rosetta Code
Task
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.

Task

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
Related task



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 division task              #
    
    LONG INT f        := 1;
    INT      fp count := 0;
    FOR n WHILE fp count < 10 DO
        f *:= n;
        CHAR fp op := "-";
        FOR offset FROM -1 BY 2 TO 1 DO
            IF  LONG INT fp = f + offset;
                is prime( fp )
            THEN
                print( ( whole( fp count +:= 1, -2 ), ":", whole( n, -4 )
                       , "! ", fp op, " 1 = ", whole( fp, 0 )
                      , newline
                      )
                    )
            FI;
            fp op := "+"
        OD
    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

Arturo

found: 0
i: 1

while [found < 10][
    fct: factorial i

    if prime? dec fct [
        found: found + 1
        print [pad (to :string found) ++ ":" 4 (to :string i)++"! - 1 = " dec fct]
    ]
    if prime? inc fct [
        found: found + 1
        print [pad (to :string found) ++ ":" 4 (to :string i)++"! + 1 = " inc fct]
    ]
    i: i + 1
]
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

BASIC

BASIC256

Translation of: FreeBASIC
include "isprime.kbs"
include "factorial.kbs"

print "First 10 factorial primes:"
found = 0
i = 1
while found < 9
	fct = factorial (i)

	if isprime(fct-1) then
		found += 1
		print rjust(string(found),2); ": "; rjust(string(i),2); "! - 1 = "; fct-1
	end if
	if isprime(fct+1) then
		found += 1
		print rjust(string(found),2); ": "; rjust(string(i),2); "! + 1 = "; fct+1
	end if
	i += 1
end while
end

Craft Basic

define found = 0, fct = 0, i = 1

do

	if found < 10 then

		let fct = factorial(i)

		if prime(fct - 1) then

			let found = found + 1
			print found, ": ", i, "! - 1 = ", fct - 1

		endif

		if prime(fct + 1) then

			let found = found + 1
			print found, ": ", i, "! + 1 = ", fct + 1

		endif

		let i = i + 1

	endif

	wait

loop found < 10

FreeBASIC

#include "isprime.bas"
#include "factorial.bas"

Print "First 10 factorial primes:"
Dim As Integer found = 0, i = 1
While found < 10
    Dim As Integer fct = factorial (i)
    
    If isprime(fct-1) Then
        found += 1
        Print Using "##: ##_! - 1 = &"; found; i; fct-1
    End If
    If isprime(fct+1) Then
        found += 1
        Print Using "##: ##_! + 1 = &"; found; i; fct+1
    End If
    i += 1
Wend
Sleep
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

Gambas

Public Sub Main()  
  
  Print "First 10 factorial primes:" 
  Dim found As Long = 0, i As Integer = 1 
  While found < 10    'más de 10 es ya BigInt
    Dim fct As Long = factorial(i) 
    
    If isPrime(fct - 1) Then 
      found += 1 
      Print Format$(found, "##"); ": "; Format$(i, "##"); "! - 1 = "; fct - 1 
    End If 
    If isPrime(fct + 1) Then 
      found += 1 
      Print Format$(found, "##"); ": "; Format$(i, "##"); "! + 1 = "; fct + 1 
    End If 
    i += 1 
  Wend
  
End

Public Sub isPrime(ValorEval As Long) As Boolean 
  
  If ValorEval < 2 Then Return False 
  If ValorEval Mod 2 = 0 Then Return ValorEval = 2 
  If ValorEval Mod 3 = 0 Then Return ValorEval = 3 
  Dim d As Long = 5 
  While d * d <= ValorEval 
    If ValorEval Mod d = 0 Then Return False Else d += 2 
  Wend  
  Return True 

End Function

Public Function factorial(num As Integer) As Long 
  
  Dim result As Long = 1 
  For i As Integer = 2 To num
    result *= i 
  Next 
  Return result
  
End
Output:
Same as FreeBASIC entry.

PureBasic

;XIncludeFile "isprime.pb"
;XIncludeFile "factorial.pb"

If OpenConsole()
  PrintN("First 10 factorial primes:")
  Define found.i = 0, i,i = 1, fct.i
  
  While found < 10
    fct = factorial (i)
    
    If isprime(fct-1)
      found + 1
      PrintN(RSet(Str(found),2) + ": " + RSet(Str(i),2) + "! - 1 = " + Str(fct-1))
    EndIf
    If isprime(fct+1)
      found + 1
      PrintN(RSet(Str(found),2) + ": " + RSet(Str(i),2) + "! + 1 = " + Str(fct+1))
    EndIf
    i + 1
  Wend
  
  PrintN(#CRLF$ + "--- terminado, pulsa RETURN---"): Input()
  CloseConsole()
EndIf
Output:
Same as FreeBASIC entry.

Run BASIC

function isPrime(n)
if n < 2       then isPrime = 0 : goto [exit]
if n = 2       then isPrime = 1 : goto [exit]
if n mod 2 = 0 then isPrime = 0 : goto [exit]
isPrime = 1
for i = 3 to int(n^.5) step 2
  if n mod i = 0 then isPrime = 0 : goto [exit]
next i
[exit]
end function

function factorial(n)
factorial = 1
if n > 1 then factorial = n * factorial(n -1)
end function

print "First 10 factorial primes:"
found = 0
i = 1
while found < 10
  fct = factorial(i)

  if isPrime(fct-1) then
    found = found + 1
    print using("##", found); ": "; using("##", i); "! - 1 = "; fct-1
  end if
  if isPrime(fct+1) then
    found = found + 1
    print using("##", found); ": "; using("##", i); "! + 1 = "; fct+1
  end if
  i = i + 1
wend

Yabasic

Translation of: FreeBASIC
import isprime
import factorial

print "First 10 factorial primes:"
found = 0
i = 1
while found < 10
    fct = factorial (i)
    
    if isPrime(fct-1) then
        found = found + 1
        print found using("##"), ": ", i using("##"), "! - 1 = ", fct-1
    fi
    if isPrime(fct+1) then
        found = found + 1
        print found using("##"), ": ", i using("##"), "! + 1 = ", fct+1
    fi
    i = i + 1
end while

C++

#include <iomanip>
#include <iostream>

#include <gmpxx.h>

using big_int = mpz_class;

std::string to_string(const big_int& num, size_t max_digits) {
    std::string str = num.get_str();
    size_t len = str.size();
    if (len > max_digits) {
        str.replace(max_digits / 2, len - max_digits, "...");
        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)

Delphi

Works with: Delphi version 6.0


function IsPrime(N: int64): boolean;
{Optimised prime test - about 40% faster than the naive approach}
var I,Stop: integer;
begin
if (N = 2) or (N=3) then Result:=true
else if (n <= 1) or ((n mod 2) = 0) or ((n mod 3) = 0) then Result:= false
else
	begin
	I:=5;
	Stop:=Trunc(sqrt(N*1.0));
	Result:=False;
	while I<=Stop do
		begin
		if ((N mod I) = 0) or ((N mod (i + 2)) = 0) then exit;
		Inc(I,6);
		end;
	Result:=True;
	end;
end;


function Factorial(N: Word): int64;
var  I: integer;
begin
Result:= 1;
for I := 2 to N do Result:=Result * I;
end;


procedure ShowFactorialPrimes(Memo: TMemo);
{Show factorials where F+1 or F-1 are prime}
var I,Cnt: integer;
var F: int64;

	procedure DisplayItem(Minus: boolean);
	var S: string;
	var Sign: char;
	var F1: int64;
	begin
	Inc(Cnt);
	if Minus then F1:=F-1 else F1:=F+1;
	if Minus then Sign:='-' else Sign:='+';
	S:=Format('%2d:   %3d! %s 1 = %d',[Cnt,I,Sign,F1]);
	Memo.Lines.Add(S);
	end;

begin
Cnt:=0;
for I:=1 to High(Integer) do
	begin
	F:=Factorial(I);
	if IsPrime(F+1) then DisplayItem(False);
	if IsPrime(F-1) then DisplayItem(True);
	if Cnt>=10 then break;
	end;
end;
Output:
 1:     1! + 1 = 2
 2:     2! + 1 = 3
 3:     3! + 1 = 7
 4:     3! - 1 = 5
 5:     4! - 1 = 23
 6:     6! - 1 = 719
 7:     7! - 1 = 5039
 8:    11! + 1 = 39916801
 9:    12! - 1 = 479001599
10:    14! - 1 = 87178291199


EasyLang

Translation of: Lua
func isprim num .
   if num < 2
      return 0
   .
   i = 2
   while i <= sqrt num
      if num mod i = 0
         return 0
      .
      i += 1
   .
   return 1
.
f = 1
while count < 10
   n += 1
   f *= n
   op$ = "-"
   for fp in [ f - 1 f + 1 ]
      if isprim fp = 1
         count += 1
         print n & "! " & op$ & " 1 = " & fp
      .
      op$ = "+"
   .
.


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]

FutureBasic

    
include "NSLog.incl"

local fn Factorial( n as NSUInteger ) as NSUInteger
  NSUInteger factorial = 1
  
  if n > 1 then factorial = n * fn Factorial( n -1 )
end fn = factorial

local fn IsPrime( n as NSUInteger ) as BOOL
  BOOL       isPrime = YES
  NSUInteger i
  
  if n < 2        then exit fn = NO
  if n = 2        then exit fn = YES
  if n mod 2 == 0 then exit fn = NO
  for i = 3 to int(n^.5) step 2
    if n mod i == 0 then exit fn = NO
  next
end fn = isPrime

void local fn FactorialPrimes( n as long )
  NSUInteger found = 0, i = 1
  
  NSLog( @"First %lu factorial primes:", n )
  while ( found < n )
    NSUInteger fct = fn Factorial( i )
    if ( fn IsPrime( fct - 1 ) )
      found++
      NSLog( @"%2lu: %3lu! - 1 = %-lu", found, i, fct - 1 )
    end if
    if ( fn IsPrime( fct + 1 ) )
      found++
      NSLog( @"%2lu: %3lu! + 1 = %-lu", found, i, fct + 1 )
    end if
    i++
  wend
end fn

fn FactorialPrimes( 10 )

HandleEvents
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


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

Sjharper79 (talk)

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.
            BigInteger biPlusOne = biFactorial.add(BigInteger.ONE); 
            
            //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))
| add

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
            PAD R " "
      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

Lua

Translation of: ALGOL 68
do -- find some factorial primes - primes that are f - 1 or f + 1
   --      for some factorial f

    function isPrime( p )
        if p <= 1 or p % 2 == 0 then
            return p == 2
        else
            local prime = true
            local i     = 3
            local rootP = math.floor( math.sqrt( p ) )
            while i <= rootP and prime do
                prime = p % i ~= 0
                i     = i + 2
            end
            return prime
        end
    end

    local f       = 1
    local fpCount = 0
    local n       = 0
    local fpOp    = ""
    while fpCount < 10 do
        n    = n + 1
        f    = f * n
        fpOp = "-"
        for fp = f - 1, f + 1, 2 do
            if isPrime( fp ) then
                fpCount = fpCount + 1
                io.write( string.format( "%2d", fpCount  ), ":"
                        , string.format( "%4d", n        ), "! "
                        , fpOp, " 1 = ", fp, "\n"
                        )
            end
            fpOp = "+"
        end
    end

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

Mathematica/Wolfram Language

Translation of: Julia
LimitedPrint[n_] := Module[{s = IntegerString[n], len},
  len = StringLength[s];
  If[len <= 40, s, StringJoin[StringTake[s, 20], "...", StringTake[s, -20], " (", ToString[len], " digits)"]]
]

ShowFactorialPrimes[N_] := Module[{f},
  Do[
    f = Factorial[i];
    If[PrimeQ[f - 1], Print[IntegerString[i, 10, 3], "! - 1 -> ", LimitedPrint[f - 1]]];
    If[PrimeQ[f + 1], Print[IntegerString[i, 10, 3], "! + 1 -> ", LimitedPrint[f + 1]]],
    {i, 1, N}
  ]
]

ShowFactorialPrimes[1000]
Output:
001! + 1 -> 2
002! + 1 -> 3
003! - 1 -> 5
003! + 1 -> 7
004! - 1 -> 23
006! - 1 -> 719
007! - 1 -> 5039
011! + 1 -> 39916801
012! - 1 -> 479001599
014! - 1 -> 87178291199
027! + 1 -> 10888869450418352160768000001
030! - 1 -> 265252859812191058636308479999999
032! - 1 -> 263130836933693530167218012159999999
033! - 1 -> 8683317618811886495518194401279999999
037! + 1 -> 13763753091226345046...79581580902400000001 (44 digits)
038! - 1 -> 52302261746660111176...24100074291199999999 (45 digits)
041! + 1 -> 33452526613163807108...40751665152000000001 (50 digits)
073! + 1 -> 44701154615126843408...03680000000000000001 (106 digits)
077! + 1 -> 14518309202828586963...48000000000000000001 (114 digits)
094! - 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)

Maxima

block([i:1,count:0,result:[]],
    while count<10 do (if primep(i!-1) or primep(i!+1) then (result:endcons(i,result),count:count+1),i:i+1),
    result:map(lambda([x],[x,x!-1,x!+1]),result),
    append(map(lambda([x],if primep(x[2]) then [x[1],x[2],"subtracted"]),result),map(lambda([x],if primep(x[3]) then [x[1],x[3],"added"]),result)),
    unique(%%),
    firstn(%%,10);
Output:
[[1,2,"added"],[2,3,"added"],[3,5,"subtracted"],[3,7,"added"],[4,23,"subtracted"],[6,719,"subtracted"],[7,5039,"subtracted"],[11,39916801,"added"],[12,479001599,"subtracted"],[14,87178291199,"subtracted"]]

Nim

Library: Nim-Integers

Nim standard integer types are limited to 64 bits. So we use an external library which provides arbitrary sized integers.

import std/[math, strformat]

# Task.

func isPrime(n: int): bool =
  if n < 2: return false
  if n == 2 or n == 3: return true
  if n mod 2 == 0: return false
  if n mod 3 == 0: return false
  var d = 5
  var step = 2
  while d * d <= n:
    if n mod d == 0:
      return false
    inc d, step
    step = 6 - step
  return true

echo "First 10 factorial primes:\n"
var count = 0
var n = 1
while count < 10:
  let f = fac(n)
  if isPrime(f - 1):
    inc count
    echo &"{count:>2}: {n:>3}! - 1 = {f - 1}"
  if count < 10 and isPrime(f + 1):
    inc count
    echo &"{count:>2}: {n:>3}! + 1 = {f + 1}"
  inc n


# Stretch.

import integers

func str(n: Integer): string =
  ## Return the string representation of an Integer.
  result = $n
  if result.len > 40:
      result = &"{result[0..19]}...{result[^20..^1]} ({result.len} digits)"

echo "\n\nNext 20 factorial primes:\n"
while count < 30:
  let f: Integer = factorial(n)
  if isPrime(f - 1):
    inc count
    echo &"{count:>2}: {n:>3}! - 1 = {str(f - 1)}"
  if isPrime(f + 1):
    inc count
    echo &"{count:>2}: {n:>3}! - 1 = {str(f + 1)}"
  inc n
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


Next 20 factorial primes:

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)

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
        mpz_add_si(e,f,k)
        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.

Python

Library: gmpy2

This takes about 32 seconds to find the first 33 factorial primes on my machine (Ryzen 5 1500X).

from itertools import count
from itertools import islice
from typing import Iterable
from typing import Tuple

import gmpy2


def factorials() -> Iterable[int]:
    fact = 1
    for i in count(1):
        yield fact
        fact *= i


def factorial_primes() -> Iterable[Tuple[int, int, str]]:
    for n, fact in enumerate(factorials()):
        if gmpy2.is_prime(fact - 1):
            yield (n, fact - 1, "-")
        if gmpy2.is_prime(fact + 1):
            yield (n, fact + 1, "+")


def print_factorial_primes(limit=10) -> None:
    print(f"First {limit} factorial primes.")
    for n, fact_prime, op in islice(factorial_primes(), 1, limit + 1):
        s = str(fact_prime)
        if len(s) > 40:
            s = f"{s[:20]}...{s[-20:]} ({len(s)} digits)"
        print(f"{n}! {op} 1 = {s}")


if __name__ == "__main__":
    import sys
    print_factorial_primes(int(sys.argv[1]) if len(sys.argv) > 1 else 10)
Output:
First 33 factorial primes.
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)

Quackery

! is defined at Factorial#Quackery.

isprime is defined at Primality by trial division#Quackery.

  [ dup 10 < if sp echo ]     is recho   ( n -->   )

  [] 0
  [ 1+ dup !
    dup dip
      [ 1 - isprime if
        [ tuck negate join swap ] ]
    1+ isprime if
      [ tuck join swap ]
    over size 9 > until ]
  drop 10 split drop
  witheach
    [ i^ 1+
      recho say ": "
      dup abs tuck recho
      0 < iff
        [ say "! - 1 = " -1 ]
      else
        [ say "! + 1 = "  1 ]
      swap ! + echo cr ]
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

Racket

#lang racket
(require gmp)

(define (factorial-boundary-stream)
  (define (factorial-stream-iter n curr-fact)
    (stream-cons `(- ,n ,(sub1 curr-fact))
                 (stream-cons `(+ ,n ,(add1 curr-fact))
                              (factorial-stream-iter (add1 n) (* curr-fact (+ n 1))))))
  (factorial-stream-iter 1 1))

(define (format-large-number n)
  (let* ([num-chars (number->string n)]
         [num-len (string-length num-chars)])
    (if (> num-len 40)
        (string-append
         (substring num-chars 0 19)
         "..."
         (substring num-chars (- num-len 19) num-len)
         (format " (total ~a digits)" num-len))
        n)))

(define (factorial-printer triple)
  (let-values ([(op n fact) (apply values triple)])
    (let ([fact (format-large-number fact)])
      (displayln (format "~a! ~a 1 = ~a" n op fact)))))

(define (prime? n)
  (not (zero? (mpz_probab_prime_p (mpz n) 10))))

(for ([i (in-stream
          (stream-take
           (stream-filter (λ (l) (prime? (third l))) (factorial-boundary-stream)) 30))]
      [n (in-naturals 1)])
  (begin
    (display (format "~a:\t" n))
    (factorial-printer i)))

;; time output of above code: 2.46 seconds
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...9581580902400000001 (total 44 digits)
16:	38! - 1 = 5230226174666011117...4100074291199999999 (total 45 digits)
17:	41! + 1 = 3345252661316380710...0751665152000000001 (total 50 digits)
18:	73! + 1 = 4470115461512684340...3680000000000000001 (total 106 digits)
19:	77! + 1 = 1451830920282858696...8000000000000000001 (total 114 digits)
20:	94! - 1 = 1087366156656743080...9999999999999999999 (total 147 digits)
21:	116! + 1 = 3393108684451898201...0000000000000000001 (total 191 digits)
22:	154! + 1 = 3089769613847350887...0000000000000000001 (total 272 digits)
23:	166! - 1 = 9003691705778437366...9999999999999999999 (total 298 digits)
24:	320! + 1 = 2116103347219252482...0000000000000000001 (total 665 digits)
25:	324! - 1 = 2288997460179102321...9999999999999999999 (total 675 digits)
26:	340! + 1 = 5100864472103711080...0000000000000000001 (total 715 digits)
27:	379! - 1 = 2484030746096470705...9999999999999999999 (total 815 digits)
28:	399! + 1 = 1600863071165597381...0000000000000000001 (total 867 digits)
29:	427! + 1 = 2906347176960734841...0000000000000000001 (total 940 digits)
30:	469! - 1 = 6771809666814951090...9999999999999999999 (total 1051 digits)
cpu time: 2440 real time: 2440 gc time: 3

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)

Ring

see "working..." + nl
load "stdlibcore.ring"

n = 0
num = 0
while true
        n++
        n1 = factorial(n) - 1
        if isPrime(n1)
           num++
           see "" + num + ": " + n + "! - 1 = " + n1 + nl
        ok
        n2 = factorial(n) + 1   
        if isPrime(n2)
           num++
           see "" + num + ": " + n + "! + 1 = " + n2 + nl
        ok 
        if num = 10
           exit
        ok
end
see "done..." + nl
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

RPL

≪ / LAST ROT * - #0 == ≫ 'MODNOT' STO

≪ R→B
   IF DUP #3 ≤ THEN #2 / B→R
   ELSE
      IF DUP #1 AND #1 ≠ OVER #3 MODNOT OR
      THEN DROP 0
      ELSE 
         DUP B→R √ R→B → maxd 
         ≪ #5 1 SF
            WHILE 1 FS? OVER maxd ≤ AND REPEAT
              IF DUP2 MODNOT THEN 1 CF END
              #2 + IF DUP2 MODNOT THEN 1 CF END
              #4 + END
         ≫
         DROP2 1 FS?
      END
   END
≫ 'PRIM?' STO

≪ 
  SWAP IP → d n 
  ≪ n →STR "!" + d 0 > "+" "" IFTE + 
     d →STR + "=" + n FACT d + →STR + 
≫ ≫ 'WRITE' STO

≪ { } 1
   WHILE OVER SIZE 10 ≤ REPEAT
     DUP FACT
     IF DUP 1 - PRIM? THEN OVER -1 WRITE 4 ROLL SWAP + ROT ROT END
     IF 1 + PRIM? THEN DUP 1 WRITE ROT SWAP + SWAP END
     1 + 
  END
≫ 'TASK' STO
Output:
1: { "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" }

Ruby

require 'openssl'

factorial_primes = Enumerator.new do |y|
  fact = 1
  (1..).each do |i|
    fact *= i
    y << [i, "- 1", fact - 1] if OpenSSL::BN.new(fact - 1).prime?
    y << [i, "+ 1", fact + 1] if OpenSSL::BN.new(fact + 1).prime?
  end
end

factorial_primes.first(30).each do |a|
  s = a.last.to_s
  if s.size > 40 then 
    puts "%d! %s = " % a.first(2) + "#{s[0,20]}...#{s[-20,20]}"
  else
    puts "%d! %s = %d" % a 
  end
end
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
38! - 1 = 52302261746660111176...24100074291199999999
41! + 1 = 33452526613163807108...40751665152000000001
73! + 1 = 44701154615126843408...03680000000000000001
77! + 1 = 14518309202828586963...48000000000000000001
94! - 1 = 10873661566567430802...99999999999999999999
116! + 1 = 33931086844518982011...00000000000000000001
154! + 1 = 30897696138473508879...00000000000000000001
166! - 1 = 90036917057784373664...99999999999999999999
320! + 1 = 21161033472192524829...00000000000000000001
324! - 1 = 22889974601791023211...99999999999999999999
340! + 1 = 51008644721037110809...00000000000000000001
379! - 1 = 24840307460964707050...99999999999999999999
399! + 1 = 16008630711655973815...00000000000000000001
427! + 1 = 29063471769607348411...00000000000000000001
469! - 1 = 67718096668149510900...99999999999999999999

Sidef

var factorial_primes = Enumerator({|f|
    for k in (1..Inf) {
        if (k!-1 -> is_prime) { f([k, -1]) }
        if (k!+1 -> is_prime) { f([k, +1]) }
    }
})

func abr(v) {
    v.len <= 40 ? v : (v.to_s.first(20) + '..' + v.to_s.last(20) + " (#{v.len} digits)")
}

factorial_primes.first(30).each_2d {|k,i|
    printf("%3d! %s %d = %s\n", k, (i.sgn < 0 ? '-' : '+'), i.abs, abr(k! + i))
}
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)

V (Vlang)

import math

fn main() {
	mut n, mut count := 0, 0
	for count < 10 {
		n++
		f := math.factoriali(n)
		if is_prime(f - 1) {
		   count++
		   println("${count}: ${n}! - 1 = ${f - 1}")
		}
		if is_prime(f + 1) {
		   count++
		   println("${count}: ${n}! + 1 = ${f + 1}")
		} 
	}
}

fn is_prime(num i64) bool {
     if num <= 1 {return false}
     if num % 2 == 0 && num != 2 {return false}
	 for idx := 3; idx <= math.floor(num / 2) - 1; idx += 2 {
         if num % idx == 0 {return false}
     }
     return true
}
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

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