Prime triangle: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Minor optimization to C code - see discussion page)
(Added FreeBASIC)
 
(30 intermediate revisions by 14 users not shown)
Line 2: Line 2:


You will require a function f which when given an integer S will return a list of the arrangements of the integers 1 to S such that g<sub>1</sub>=1 g<sub>S</sub>=S and generally for n=1 to n=S-1 g<sub>n</sub>+g<sub>n+1</sub> is prime. S=1 is undefined. For S=2 to S=20 print f(S) to form a triangle. Then again for S=2 to S=20 print the number of possible arrangements of 1 to S meeting these requirements.
You will require a function f which when given an integer S will return a list of the arrangements of the integers 1 to S such that g<sub>1</sub>=1 g<sub>S</sub>=S and generally for n=1 to n=S-1 g<sub>n</sub>+g<sub>n+1</sub> is prime. S=1 is undefined. For S=2 to S=20 print f(S) to form a triangle. Then again for S=2 to S=20 print the number of possible arrangements of 1 to S meeting these requirements.


;See also
:* [[oeis:A036440|OEIS:A036440]]



=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
Line 7: Line 12:
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
As Algol 68G under Windows is fully interpreted, a reduced number of rows is produced.
As Algol 68G under Windows is fully interpreted, a reduced number of rows is produced.
<lang algol68>BEGIN # find solutions to the "Prime Triangle" - a triangle of numbers that sum to primes #
<syntaxhighlight lang="algol68">BEGIN # find solutions to the "Prime Triangle" - a triangle of numbers that sum to primes #
INT max number = 18; # largest number we will consider #
INT max number = 18; # largest number we will consider #
# construct a primesieve and from that a table of pairs of numbers whose sum is prime #
# construct a primesieve and from that a table of pairs of numbers whose sum is prime #
Line 20: Line 25:
FI
FI
OD;
OD;
[ 1 : max number, 1 : max number ]BOOL prime pair;
FOR a TO max number DO
prime pair[ a, 1 ] := FALSE;
FOR b FROM 2 TO max number DO
prime pair[ a, b ] := prime[ a + b ]
OD;
prime pair[ a, a ] := FALSE
OD;
# finds the next number that can follow i or 0 if there isn't one #
PROC find next = ( INT i, INT n, INT current, []BOOL used )INT:
BEGIN
# the numbers must alternate between even and odd in order for the sum to be prime #
INT result := IF current > 0 THEN current + 2
ELIF ODD i THEN 2
ELSE 3
FI;
WHILE IF result >= n THEN FALSE ELSE NOT prime pair[ i, result ] OR used[ result ] FI DO
result +:= 2
OD;
IF result >= n THEN 0 ELSE result FI
END # find next # ;
# returns the number of possible arrangements of the integers for a row in the prime triangle #
# returns the number of possible arrangements of the integers for a row in the prime triangle #
PROC count arrangements = ( INT n, BOOL print solution )INT:
PROC count arrangements = ( INT n )INT:
IF n < 2 THEN # no solutions for n < 2 # 0
IF n < 2 THEN # no solutions for n < 2 # 0
ELIF n < 4 THEN
ELIF n < 4 THEN
# for 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3 #
# for 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3 #
IF print solution THEN
FOR i TO n DO print( ( whole( i, -3 ) ) ) OD; print( ( newline ) );
FOR i TO n DO print( ( whole( i, -3 ) ) ) OD; print( ( newline ) )
FI;
1
1
ELSE
ELSE
# 4 or more - must find the solutions #
# 4 or more - must find the solutions #
BOOL print solution := TRUE;
[ 0 : n ]BOOL used;
[ 0 : n ]BOOL used;
[ 0 : n ]INT number;
[ 0 : n ]INT number;
# the triangle row must have 1 in the leftmost and n in the rightmost elements #
# the numbers must alternate between even and odd in order for the sum to be prime #
FOR i FROM 0 TO n DO
FOR i FROM 0 TO n DO
used[ i ] := FALSE;
used[ i ] := FALSE;
number[ i ] := 0
number[ i ] := i MOD 2
OD;
OD;
used[ 1 ] := TRUE;
# the triangle row must have 1 in the leftmost and n in the rightmost elements #
number[ 1 ] := 1; used[ 1 ] := TRUE;
number[ n ] := n;
number[ n ] := n; used[ n ] := TRUE;
used[ n ] := TRUE;
# find the intervening numbers and count the solutions #
# find the intervening numbers and count the solutions #
INT count := 0;
INT count := 0;
INT p := 2;
INT p := 2;
WHILE p < n DO
WHILE p > 0 DO
INT pn = number[ p - 1 ];
INT p1 = number[ p - 1 ];
INT next := find next( pn, n, number[ p ], used );
INT current = number[ p ];
INT next := current + 2;
WHILE IF next >= n THEN FALSE ELSE NOT prime[ p1 + next ] OR used[ next ] FI DO
next +:= 2
OD;
IF next >= n THEN next := 0 FI;
IF p = n - 1 THEN
IF p = n - 1 THEN
# we are at the final number before n #
# we are at the final number before n #
WHILE IF next = 0 THEN FALSE ELSE NOT prime pair[ next, n ] FI DO
# it must be the final even/odd number preceded by the final odd/even number #
next := find next( pn, n, next, used )
IF next /= 0 THEN
OD
# possible solution #
IF prime[ next + n ] THEN
# found a solution #
count +:= 1;
IF print solution THEN
FOR i TO n - 2 DO
print( ( whole( number[ i ], -3 ) ) )
OD;
print( ( whole( next, -3 ), whole( n, - 3 ), newline ) );
print solution := FALSE
FI
FI;
next := 0
FI;
# backtrack for more solutions #
p -:= 1
# here will be a further backtrack as next is 0 ( there could only be one possible number at p - 1 ) #
FI;
FI;
IF next /= 0 THEN
IF next /= 0 THEN
# have a/another number that can appear at p #
# have a/another number that can appear at p #
used[ number[ p ] ] := FALSE;
used[ current ] := FALSE;
used[ next ] := TRUE;
used[ next ] := TRUE;
number[ p ] := next;
number[ p ] := next;
IF p < n - 1 THEN
p +:= 1
# haven't found all the intervening digits yet #
p +:= 1;
number[ p ] := 0
ELSE
# found a solution #
count +:= 1;
IF count = 1 AND print solution THEN
FOR i TO n DO
print( ( whole( number[ i ], -3 ) ) )
OD;
print( ( newline ) )
FI;
# backtrack for more solutions #
used[ number[ p ] ] := FALSE;
number[ p ] := 0;
p -:= 1
FI
ELIF p <= 2 THEN
ELIF p <= 2 THEN
# no more solutions #
# no more solutions #
p := n
p := 0
ELSE
ELSE
# can't find a number for this position, backtrack #
# can't find a number for this position, backtrack #
used[ number[ p ] ] := FALSE;
used[ number[ p ] ] := FALSE;
number[ p ] := 0;
number[ p ] := p MOD 2;
p -:= 1
p -:= 1
FI
FI
Line 110: Line 99:
[ 2 : max number ]INT arrangements;
[ 2 : max number ]INT arrangements;
FOR n FROM LWB arrangements TO UPB arrangements DO
FOR n FROM LWB arrangements TO UPB arrangements DO
arrangements[ n ] := count arrangements( n, TRUE )
arrangements[ n ] := count arrangements( n )
OD;
OD;
FOR n FROM LWB arrangements TO UPB arrangements DO
FOR n FROM LWB arrangements TO UPB arrangements DO
Line 116: Line 105:
OD;
OD;
print( ( newline ) )
print( ( newline ) )
END</syntaxhighlight>
END
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 138: Line 126:
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464
</pre>

=={{header|BASIC}}==
==={{header|FreeBASIC}}===
{{trans|Visual Basic .NET}}
<syntaxhighlight lang="vbnet">Dim Shared As Uinteger maxNumber = 20 ' Largest number we will consider.
Dim Shared As Uinteger prime(2 * maxNumber) ' prime sieve.

Function countArrangements(Byval n As Uinteger) As Uinteger
Dim As Uinteger i
If n < 2 Then ' No solutions for n < 2.
Return 0
Elseif n < 4 Then
' For 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3.
For i = 1 To n
Print Using "###"; i;
Next i
Print
Return 1
Else
' 4 or more - must find the solutions.
Dim As Boolean printSolution = True
Dim As Boolean used(n)
Dim As Uinteger number(n)
' The triangle row must have 1 in the leftmost and n in the rightmost elements.
' The numbers must alternate between even and odd in order for the sums to be prime.
For i = 0 To n - 1
number(i) = i Mod 2
Next i
used(1) = True
number(n) = n
used(n) = True
' Find the intervening numbers and count the solutions.
Dim As Uinteger count = 0
Dim As Uinteger p = 2
Do While p > 0
Dim As Uinteger p1 = number(p - 1)
Dim As Uinteger current = number(p)
Dim As Uinteger sgte = current + 2
Do While sgte < n Andalso (Not prime(p1 + sgte) Or used(sgte))
sgte += 2
Loop
If sgte >= n Then
sgte = 0
End If
If p = n - 1 Then
' We are at the final number before n.
' It must be the final even/odd number preceded by the final odd/even number.
If sgte <> 0 Then
' Possible solution.
If prime(sgte + n) Then
' Found a solution.
count += 1
If printSolution Then
For i = 1 To n - 2
Print Using "###"; number(i);
Next i
Print Using "###"; sgte; n
printSolution = False
End If
End If
sgte = 0
End If
' Backtrack for more solutions.
p -= 1
' There will be a further backtrack as next is 0 ( there could only be one possible number at p - 1 ).
End If
If sgte <> 0 Then
' have a/another number that can appear at p.
used(current) = False
used(sgte) = True
number(p) = sgte
' Haven't found all the intervening digits yet.
p += 1
Elseif p <= 2 Then
' No more solutions.
p = 0
Else
' Can't find a number for this position, backtrack.
used(number(p)) = False
number(p) = p Mod 2
p -= 1
End If
Loop
Return count
End If
End Function

Dim As Integer i, s, n
prime(2) = True
For i = 3 To Ubound(prime) Step 2
prime(i) = True
Next i
For i = 3 To Cint(Sqr(Ubound(prime))) Step 2
If prime(i) Then
For s = i * i To Ubound(prime) Step i + i
prime(s) = False
Next s
End If
Next i

Dim As Integer arrangements(maxNumber)
For n = 2 To Ubound(arrangements)
arrangements(n) = countArrangements(n)
Next n
For n = 2 To Ubound(arrangements)
Print arrangements(n);
Next n
Print

Sleep</syntaxhighlight>
{{out}}
<pre>Same as Visual Basic .NET entry.</pre>

==={{header|Visual Basic .NET}}===
{{Trans|ALGOL 68}}
<syntaxhighlight lang="vbnet">Option Strict On
Option Explicit On

Imports System.IO

''' <summary>Find solutions to the "Prime Triangle" - a triangle of numbers that sum to primes.</summary>
Module vMain

Public Const maxNumber As Integer = 20 ' Largest number we will consider.
Dim prime(2 * maxNumber) As Boolean ' prime sieve.

''' <returns>The number of possible arrangements of the integers for a row in the prime triangle.</returns>
Public Function countArrangements(ByVal n As Integer) As Integer
If n < 2 Then ' No solutions for n < 2.
Return 0
ElseIf n < 4 Then
' For 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3.
For i As Integer = 1 To n
Console.Out.Write(i.ToString.PadLeft(3))
Next i
Console.Out.WriteLine()
Return 1
Else
' 4 or more - must find the solutions.
Dim printSolution As Boolean = true
Dim used(n) As Boolean
Dim number(n) As Integer
' The triangle row must have 1 in the leftmost and n in the rightmost elements.
' The numbers must alternate between even and odd in order for the sums to be prime.
For i As Integer = 0 To n - 1
number(i) = i Mod 2
Next i
used(1) = True
number(n) = n
used(n) = True
' Find the intervening numbers and count the solutions.
Dim count As Integer = 0
Dim p As Integer = 2
Do While p > 0
Dim p1 As Integer = number(p - 1)
Dim current As Integer = number(p)
Dim [next] As Integer = current + 2
Do While [next] < n AndAlso (Not prime(p1 + [next]) Or used([next]))
[next] += 2
Loop
If [next] >= n Then
[next] = 0
End If
If p = n - 1 Then
' We are at the final number before n.
' It must be the final even/odd number preceded by the final odd/even number.
If [next] <> 0 Then
' Possible solution.
If prime([next] + n) Then
' Found a solution.
count += 1
If printSolution Then
For i As Integer = 1 To n - 2
Console.Out.Write(number(i).ToString.PadLeft(3))
Next i
Console.Out.WriteLine([next].ToString.PadLeft(3) & n.ToString.PadLeft(3))
printSolution = False
End If
End If
[next] = 0
End If
' Backtrack for more solutions.
p -= 1
' There will be a further backtrack as next is 0 ( there could only be one possible number at p - 1 ).
End If
If [next] <> 0 Then
' have a/another number that can appear at p.
used(current) = False
used([next]) = True
number(p) = [next]
' Haven't found all the intervening digits yet.
p += 1
ElseIf p <= 2 Then
' No more solutions.
p = 0
Else
' Can't find a number for this position, backtrack.
used(number(p)) = False
number(p) = p Mod 2
p -= 1
End If
Loop
Return count
End If
End Function

Public Sub Main
prime(2) = True
For i As Integer = 3 To UBound(prime) Step 2
prime(i) = True
Next i
For i As Integer = 3 To Convert.ToInt32(Math.Floor(Math.Sqrt(Ubound(prime)))) Step 2
If prime(i) Then
For s As Integer = i * i To Ubound(prime) Step i + i
prime(s) = False
Next s
End If
Next i

Dim arrangements(maxNumber) As Integer
For n As Integer = 2 To UBound(arrangements)
arrangements(n) = countArrangements(n)
Next n
For n As Integer = 2 To UBound(arrangements)
Console.Out.Write(" " & arrangements(n))
Next n
Console.Out.WriteLine()

End Sub

End Module</syntaxhighlight>
{{out}}
<pre>
1 2
1 2 3
1 2 3 4
1 4 3 2 5
1 4 3 2 5 6
1 4 3 2 5 6 7
1 2 3 4 7 6 5 8
1 2 3 4 7 6 5 8 9
1 2 3 4 7 6 5 8 9 10
1 2 3 4 7 10 9 8 5 6 11
1 2 3 4 7 10 9 8 5 6 11 12
1 2 3 4 7 6 5 12 11 8 9 10 13
1 2 3 4 7 6 13 10 9 8 11 12 5 14
1 2 3 4 7 6 13 10 9 8 11 12 5 14 15
1 2 3 4 7 6 5 12 11 8 15 14 9 10 13 16
1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14 17
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
</pre>
</pre>


=={{header|C}}==
=={{header|C}}==
<lang c>#include <assert.h>
<syntaxhighlight lang="c">#include <assert.h>
#include <stdbool.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdio.h>
Line 224: Line 466:
printf("\nElapsed time: %f seconds\n", duration);
printf("\nElapsed time: %f seconds\n", duration);
return 0;
return 0;
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 252: Line 494:
Elapsed time: 0.572986 seconds
Elapsed time: 0.572986 seconds
</pre>
</pre>

=== Use bit patterns ===
Number combinations are all stored in bit positions here. The <code>bpos()</code> functions returns the position index of the least significant bit in an integer. This code gains some speed, at the cost of total loss of readability. On the plus side, it has some bit manipulation tricks that may be interesting to some.

<syntaxhighlight lang="c">#include <stdio.h>
#include <stdint.h>

#define GCC_ASM // use GCC's asm for i386. If it does not work, #undef it to use alternative func
typedef uint32_t uint;
typedef uint64_t ulong;

#define MASK 0xa08228828228a2bULL

#ifdef GCC_ASM

static inline uint
bpos(uint x)
{
uint b;
asm("bsf %0, %0" : "=r" (b): "0" (x));
return b;
}

#else

static inline uint
bpos(uint x)
{
static const uint bruijin[32] = {
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
return bruijin[((uint)((x & -x) * 0x077CB531U)) >> 27];
}

#endif // GCC_ASM

int count(uint n, const uint s, uint avail)
{
int cnt = 0;

avail ^= s;
if (--n)
for (uint b = (uint)(MASK>>bpos(s)) & avail; b; b &= b-1)
cnt += count(n, b&-b, avail);
else
return (MASK & s) != 0;

return cnt;
}

int disp(uint n, const uint s, uint avail, int maxn, uint *seq)
{
seq[n--] = s;
if (!n) {
if ((MASK & s)) {
for (int i = 0; i < maxn; i++)
printf(" %d", bpos(seq[i]) + 1);
putchar('\n');
return 1;
}
} else {
for (uint b = (uint)(MASK>>bpos(s)) & (avail ^= s); b; b &= b-1)
if (disp(n, b&-b, avail, maxn, seq))
return 1;
}
return 0;
}

int chain(uint n, int count_only)
{
const uint top = 1U<<(n - 1);
const uint avail = 2*top - 2;

if (count_only)
return count(n - 1, top, avail);

uint seq[32];
seq[0] = 1;
disp(n - 1, top, avail, n, seq);

return 0;
}

int main(void)
{
for (int n = 2; n < 21; n++)
chain(n, 0);
putchar('\n');

for (int n = 2; n < 21; n++)
printf("%d ", chain(n, 1));
putchar('\n');

return 0;
}</syntaxhighlight>
{{out}}
<pre> 1 2
1 2 3
1 2 3 4
1 4 3 2 5
1 4 3 2 5 6
1 6 5 2 3 4 7
1 4 7 6 5 2 3 8
1 4 7 6 5 8 3 2 9
1 6 7 4 9 8 5 2 3 10
1 10 9 8 5 6 7 4 3 2 11
1 10 9 8 11 6 7 4 3 2 5 12
1 12 11 8 9 10 7 6 5 2 3 4 13
1 12 11 8 9 10 13 4 7 6 5 2 3 14
1 12 11 8 5 14 9 10 13 6 7 4 3 2 15
1 12 11 8 15 14 9 10 13 4 7 6 5 2 3 16
1 10 13 16 15 14 9 8 11 12 5 6 7 4 3 2 17
1 12 17 14 15 16 13 10 9 8 11 6 7 4 3 2 5 18
1 18 13 16 15 14 17 12 11 8 9 10 7 6 5 2 3 4 19
1 18 19 10 13 16 15 14 17 12 11 8 9 4 7 6 5 2 3 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162</pre>


=={{header|C++}}==
=={{header|C++}}==
<lang cpp>#include <cassert>
<syntaxhighlight lang="cpp">#include <cassert>
#include <chrono>
#include <chrono>
#include <iomanip>
#include <iomanip>
Line 330: Line 690:
std::chrono::duration<double> duration(end - start);
std::chrono::duration<double> duration(end - start);
std::cout << "\nElapsed time: " << duration.count() << " seconds\n";
std::cout << "\nElapsed time: " << duration.count() << " seconds\n";
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 361: Line 721:
=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
This task uses [http://www.rosettacode.org/wiki/Extensible_prime_generator#The_functions Extensible Prime Generator (F#)]
This task uses [http://www.rosettacode.org/wiki/Extensible_prime_generator#The_functions Extensible Prime Generator (F#)]
<lang fsharp>
<syntaxhighlight lang="fsharp">
// Prime triangle. Nigel Galloway: April 12th., 2022
// Prime triangle. Nigel Galloway: April 12th., 2022
let fN i (g,(e,l))=e|>Seq.map(fun n->let n=i n in (n::g,List.partition(i>>(=)n) l))
let fN i (g,(e,l))=e|>Seq.map(fun n->let n=i n in (n::g,List.partition(i>>(=)n) l))
Line 370: Line 730:
{2..20}|>Seq.iter(fun n->(primeT>>Seq.head>>List.iter(printf "%3d"))n;printfn "");;
{2..20}|>Seq.iter(fun n->(primeT>>Seq.head>>List.iter(printf "%3d"))n;printfn "");;
{2..20}|>Seq.iter(primeT>>Seq.length>>printf "%d "); printfn ""
{2..20}|>Seq.iter(primeT>>Seq.length>>printf "%d "); printfn ""
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 397: Line 757:


=={{header|Go}}==
=={{header|Go}}==
Takes about 0.64 seconds.
{{trans|Phix}}
{{trans|Phix}}
<lang go>package main
<syntaxhighlight lang="go">package main


import "fmt"
import "fmt"


var canFollow [][]bool
var canFollow [][]bool
var avail []bool
var arrang []int
var arrang []int
var bCount = false
var bFirst = true


var pmap = make(map[int]bool)
var pmap = make(map[int]bool)
Line 419: Line 779:
if n-done <= 1 {
if n-done <= 1 {
if canFollow[ad-1][n-1] {
if canFollow[ad-1][n-1] {
if !bCount {
if bFirst {
for _, e := range arrang {
for _, e := range arrang {
fmt.Printf("%2d ", e)
fmt.Printf("%2d ", e)
}
}
fmt.Println()
fmt.Println()
bFirst = false
}
}
res++
res++
Line 429: Line 790:
} else {
} else {
done++
done++
for i := 1; i <= n-2; i++ {
for i := done - 1; i <= n-2; i += 2 {
if avail[i] && canFollow[ad-1][i] {
ai := arrang[i]
avail[i] = false
if canFollow[ad-1][ai-1] {
arrang[done-1] = i + 1
arrang[i], arrang[done-1] = arrang[done-1], arrang[i]
res = ptrs(res, n, done)
res = ptrs(res, n, done)
if !bCount && res != 0 {
arrang[i], arrang[done-1] = arrang[done-1], arrang[i]
return res
}
avail[i] = true
}
}
}
}
Line 453: Line 811:
}
}
}
}
avail = make([]bool, n)
bFirst = true
for i := 1; i < n-1; i++ {
arrang = make([]int, n)
avail[i] = true
for i := 0; i < n; i++ {
arrang[i] = i + 1
}
}
arrang = make([]int, n)
arrang[0] = 1
arrang[n-1] = n
return ptrs(0, n, 1)
return ptrs(0, n, 1)
}
}


func main() {
func main() {
counts := make([]int, 19)
for i := 2; i <= 20; i++ {
for i := 2; i <= 20; i++ {
primeTriangle(i)
counts[i-2] = primeTriangle(i)
}
}
fmt.Println()
fmt.Println()
bCount = true
for i := 0; i < 19; i++ {
for i := 2; i <= 20; i++ {
fmt.Printf("%d ", counts[i])
fmt.Printf("%d ", primeTriangle(i))
}
}
fmt.Println()
fmt.Println()
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 502: Line 858:
=={{header|J}}==
=={{header|J}}==


Essentially, we're traversing a directed graph starting at 1, ending at y, with edges such that adjacent pairs sum to a prime number and with distinct intermediate values between 1 and y.
Paraphrase of [[#C|C]] based on [[oeis:wiki/Prime triangles|OEIS]]:


Implementation:
<lang J>is_prime=: 1&p:@(+/)


<syntaxhighlight lang="j">add_plink=: [:;{{ <y,"1 0 x #~ 1 p:+/|:(x=. x-. y),"0/{: y }}"1
is_prime_triangle=: {{
prime_pair_seqs=: {{ y add_plink (2}.i.y) add_plink^:(y-2) 1 }}</syntaxhighlight>
NB. y is index into L and thus analogous to *a
p=. is_prime L{~y+0 1
if. N=y do. p return.end.
i=. Y=. y+1
if. p do. if. is_prime_triangle Y do. 1 return.end.end.
while. M>i=.i+2 do.
if. is_prime L{~y,i do.
L=: (L{~Y,i) (i,Y)} L
if. is_prime_triangle Y do. 1 return.end.
L=: (L{~Y,i) (i,Y)} L
end.
end.
0
}}


Task example (displaying counts of number of valid sequences to the left, because that looks nice):
prime_triangle_counter=: {{

NB. y is index into L and thus analogous to *a
<syntaxhighlight lang="j">task=: {{
p=. is_prime L{~y+0 1
if. N=y do.
for_j.2}.i.1+y do.
N=. #seqs=. prime_pair_seqs j
count=: count+p return.
echo (_8{.":N),' | ',3":{:seqs
end.
end.
i=. Y=. y+1
if. p do. prime_triangle_counter Y end.
while. M>i=. i+2 do.
if. is_prime L{~y,i do.
L=: (L{~Y,i) (i,Y)} L
prime_triangle_counter Y
L=: (L{~Y,i) (i,Y)} L
end.
end.
count
}}
}}


task 20
prime_triangles=: {{
for_k. i.y-1 do.
L=: l=. 1+i.1+M=: 1+N=: k
count=: 0
prime_triangle_counter 0
L=: l
assert is_prime_triangle 0
echo (8":count),' | ',3":L
end.
}}</lang>

Task example:

<lang J>
prime_triangles 20
1 | 1 2
1 | 1 2
1 | 1 2 3
1 | 1 2 3
Line 560: Line 880:
1 | 1 4 3 2 5
1 | 1 4 3 2 5
1 | 1 4 3 2 5 6
1 | 1 4 3 2 5 6
2 | 1 4 3 2 5 6 7
2 | 1 6 5 2 3 4 7
4 | 1 2 3 4 7 6 5 8
4 | 1 6 7 4 3 2 5 8
7 | 1 2 3 4 7 6 5 8 9
7 | 1 6 7 4 3 8 5 2 9
24 | 1 2 3 4 7 6 5 8 9 10
24 | 1 6 7 4 9 8 5 2 3 10
80 | 1 2 3 4 7 10 9 8 5 6 11
80 | 1 10 9 8 5 6 7 4 3 2 11
216 | 1 2 3 4 7 10 9 8 5 6 11 12
216 | 1 10 9 8 11 6 7 4 3 2 5 12
648 | 1 2 3 4 7 6 5 12 11 8 9 10 13
648 | 1 12 11 8 9 10 7 6 5 2 3 4 13
1304 | 1 2 3 4 7 6 13 10 9 8 11 12 5 14
1304 | 1 12 11 8 9 10 13 6 7 4 3 2 5 14
3392 | 1 2 3 4 7 6 13 10 9 8 11 12 5 14 15
3392 | 1 12 11 8 9 14 5 6 13 10 7 4 3 2 15
13808 | 1 2 3 4 7 6 5 12 11 8 15 14 9 10 13 16
13808 | 1 12 11 8 15 14 9 10 13 6 5 2 3 4 7 16
59448 | 1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14 17
59448 | 1 16 15 14 9 10 13 6 11 12 7 4 3 8 5 2 17
155464 | 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
155464 | 1 16 15 14 17 12 11 8 9 10 13 6 7 4 3 2 5 18
480728 | 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
480728 | 1 18 13 16 15 14 17 12 11 8 9 10 7 6 5 2 3 4 19
1588162 | 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20</lang>
1588162 | 1 18 19 12 17 14 15 16 13 10 9 8 11 2 5 6 7 4 3 20</syntaxhighlight>


=={{header|Java}}==
=={{header|Java}}==
<lang java>public class PrimeTriangle {
<syntaxhighlight lang="java">public class PrimeTriangle {
public static void main(String[] args) {
public static void main(String[] args) {
long start = System.currentTimeMillis();
long start = System.currentTimeMillis();
Line 613: Line 933:
if (length == 2)
if (length == 2)
return isPrime(a[start] + a[start + 1]);
return isPrime(a[start] + a[start + 1]);
for (int i = 1; i + 1 < length; ++i) {
for (int i = 1; i + 1 < length; i += 2) {
if (isPrime(a[start] + a[start + i])) {
if (isPrime(a[start] + a[start + i])) {
swap(a, start + i, start + 1);
swap(a, start + i, start + 1);
Line 630: Line 950:
++count;
++count;
} else {
} else {
for (int i = 1; i + 1 < length; ++i) {
for (int i = 1; i + 1 < length; i += 2) {
if (isPrime(a[start] + a[start + i])) {
if (isPrime(a[start] + a[start + i])) {
swap(a, start + i, start + 1);
swap(a, start + i, start + 1);
Line 650: Line 970:
return ((1L << n) & 0x28208a20a08a28acL) != 0;
return ((1L << n) & 0x28208a20a08a28acL) != 0;
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 676: Line 996:
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162


Elapsed time: 977 milliseconds
Elapsed time: 833 milliseconds
</pre>

=={{header|jq}}==
{{works with|jq}}
'''Adapted from [[#Wren|Wren]]'''

(gojq requires too much memory to complete the task.)
<syntaxhighlight lang=jq>
# $i and $j should be relevant integers (possibly negataive)
# Usage with an array-valued key: .key |= array_swap($i; $j)
def array_swap($i; $j):
if $i == $j then .
else .[$i] as $t
| .[$i] = .[$j]
| .[$j] = $t
end;

# For syntactic convenience
def swap($array; $i; $j):
$array | array_swap($i; $j);

def pmap:
reduce (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37) as $i ([];
.[$i] = true) ;

# input: {bFirst, arrang, canFollow, emit}
# output: same + {res, emit, i, count}
def ptrs($res; $n; $done):
. + {$res, count: $done}
| .arrang[$done-1] as $ad
| if ($n - $done <= 1)
then if .canFollow[$ad-1][$n-1]
then if .bFirst
then .emit += [.arrang]
| .bFirst = false
else .
end
| .res += 1
else .
end
else .count += 1
| .count as $count
| reduce range($count - 1; $n - 1; 2) as $i (.;
.arrang[$i] as $ai
| if .canFollow[$ad-1][$ai-1]
then .arrang = swap(.arrang; $i; $count-1)
| ptrs(.res; $n; $count)
| .arrang = swap(.arrang; $i; $count-1)
else .
end )
end;

# Emit {emit, res} from the call to ptrs
def primeTriangle($n):
pmap as $pmap
| {}
| .canFollow = (reduce range(0;$n) as $i ([];
.[$i] = [range(0;$n) | false]
| reduce range(0;$n) as $j (.;
.[$i][$j] = $pmap[$i+$j+2] )))
| .bFirst = true
| .arrang = [range(1; 1+$n)]
| ptrs(0; $n; 1)
| {emit, res} ;

def task($n):
range(2;$n+1) as $i
| primeTriangle($i) ;

def task($n):
foreach (range(2;$n+1), null) as $i ({counts: [], emit: null};
if $i == null then .emit = "\n\(.counts)"
else primeTriangle($i) as $pt
| .counts += [$pt|.res]
| .emit = $pt.emit
end;
.emit);

task(20)[]
</syntaxhighlight>
{{output}}
<pre>
[1,2]
[1,2,3]
[1,2,3,4]
[1,4,3,2,5]
[1,4,3,2,5,6]
[1,4,3,2,5,6,7]
[1,2,3,4,7,6,5,8]
[1,2,3,4,7,6,5,8,9]
[1,2,3,4,7,6,5,8,9,10]
[1,2,3,4,7,10,9,8,5,6,11]
[1,2,3,4,7,10,9,8,5,6,11,12]
[1,2,3,4,7,6,5,12,11,8,9,10,13]
[1,2,3,4,7,6,13,10,9,8,11,12,5,14]
[1,2,3,4,7,6,13,10,9,8,11,12,5,14,15]
[1,2,3,4,7,6,5,12,11,8,15,14,9,10,13,16]
[1,2,3,4,7,6,5,12,11,8,9,10,13,16,15,14,17]
[1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,11,18]
[[1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,11,18,19]]
[[1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,19,18,11,20]]

[1,1,1,1,1,2,4,7,24,80,216,648,1304,3392,13808,59448,155464,480728,1588162]
</pre>
</pre>


=={{header|Julia}}==
=={{header|Julia}}==
=== Filter method ===
=== Filter method ===
<lang julia>using Combinatorics, Primes
<syntaxhighlight lang="julia">using Combinatorics, Primes


function primetriangle(nrows::Integer)
function primetriangle(nrows::Integer)
Line 712: Line 1,135:


@time primetriangle(16)
@time primetriangle(16)
</lang>{{out}}
</syntaxhighlight>{{out}}
<pre>
<pre>
1 2
1 2
Line 736: Line 1,159:
=== Generator method ===
=== Generator method ===
Similar to the Phix entry.
Similar to the Phix entry.
<lang julia>using Primes
<syntaxhighlight lang="julia">using Primes


function solverow(row, pos, avail)
function solverow(row, pos, avail)
Line 768: Line 1,191:
println(" 1 2\n" * prod(rowstrings), "\n", counts)
println(" 1 2\n" * prod(rowstrings), "\n", counts)
end
end
</lang> {{out}}
</syntaxhighlight> {{out}}
<pre>
<pre>
1 2
1 2
Line 793: Line 1,216:
25.818809 seconds (249.58 M allocations: 22.295 GiB, 15.56% gc time)
25.818809 seconds (249.58 M allocations: 22.295 GiB, 15.56% gc time)
</pre>
</pre>

=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[FindPrimeTriangles, FindPrimeTrianglesHelper]
FindPrimeTriangles[max_] :=
Module[{count = 0, firstsolution, primes, primeQ},
primes = PrimeQ[Range[2 max]];
primeQ[n_] := primes[[n]];
ClearAll[FindPrimeTrianglesHelper];
FindPrimeTrianglesHelper[start_, remainder_, mxx_] :=
Module[{last, nexts, r, newstart, newremainder},
If[Length[remainder] > 0,
last = Last[start];
Do[
r = remainder[[ri]];
If[primeQ[last + r],
newstart = Append[start, r];
newremainder = Delete[remainder, ri];
FindPrimeTrianglesHelper[newstart, newremainder, mxx]
]
,
{ri, Length[remainder]}
]
,
If[primeQ[Last[start] + mxx],
count++;
If[count == 1,
Print[Append[start, mxx]]
]
]
]
];
FindPrimeTrianglesHelper[{1}, Range[2, max - 1], max];
count
]
Table[FindPrimeTriangles[S],{S, 2, 20}]</syntaxhighlight>
{{out}}
<pre>{1,2}
{1,2,3}
{1,2,3,4}
{1,4,3,2,5}
{1,4,3,2,5,6}
{1,4,3,2,5,6,7}
{1,2,3,4,7,6,5,8}
{1,2,3,4,7,6,5,8,9}
{1,2,3,4,7,6,5,8,9,10}
{1,2,3,4,7,10,9,8,5,6,11}
{1,2,3,4,7,10,9,8,5,6,11,12}
{1,2,3,4,7,6,5,12,11,8,9,10,13}
{1,2,3,4,7,6,13,10,9,8,11,12,5,14}
{1,2,3,4,7,6,13,10,9,8,11,12,5,14,15}
{1,2,3,4,7,6,5,12,11,8,15,14,9,10,13,16}
{1,2,3,4,7,6,5,12,11,8,9,10,13,16,15,14,17}
{1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,11,18}
{1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,11,18,19}
{1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,19,18,11,20}

{1, 1, 1, 1, 1, 2, 4, 7, 24, 80, 216, 648, 1304, 3392, 13808, 59448, 155464, 480728, 1588162}</pre>

=={{header|Nim}}==
{{trans|C}}
<syntaxhighlight lang="Nim">import std/[monotimes, strutils, times]

const IsPrime = [false, false, true, true, false, true, false, true,
false, false, false, true, false, true, false, false,
false, true, false, true, false, false, false, true,
false, false, false, false, false, true, false, true,
false, false, false, false, false, true, false, false,
false, true, false, true, false, false, false, true,
false, false, false, false, false, true, false, false,
false, false, false, true, false, true, false, false]

type TriangleRow = openArray[Natural]

template isPrime(n: Natural): bool = IsPrime[n]

func primeTriangleRow(a: var TriangleRow): bool =
if a.len == 2:
return isPrime(a[0] + a[1])
for i in countup(1, a.len - 2, 2):
if isPrime(a[0] + a[i]):
swap a[i], a[1]
if primeTriangleRow(a.toOpenArray(1, a.high)):
return true
swap a[i], a[1]

func primeTriangleCount(a: var TriangleRow): Natural =
if a.len == 2:
if isPrime(a[0] + a[1]):
inc result
else:
for i in countup(1, a.len - 2, 2):
if isPrime(a[0] + a[i]):
swap a[i], a[1]
inc result, primeTriangleCount(a.toOpenArray(1, a.high))
swap a[i], a[1]

proc print(a: TriangleRow) =
if a.len == 0: return
for i, n in a:
if n > 0: stdout.write ' '
stdout.write align($n, 2)
stdout.write '\n'

let start = getMonoTime()
for n in 2..20:
var a = newSeq[Natural](n)
for i in 0..<n:
a[i] = i + 1
if a.primeTriangleRow:
print a
echo()
for n in 2..20:
var a = newSeq[Natural](n)
for i in 0..<n:
a[i] = i + 1
if n > 2: stdout.write " "
stdout.write a.primeTriangleCount
echo '\n'

echo "Elapsed time: ", (getMonoTime() - start).inMilliseconds, " ms"
</syntaxhighlight>

{{out}}
<pre> 1 2
1 2 3
1 2 3 4
1 4 3 2 5
1 4 3 2 5 6
1 4 3 2 5 6 7
1 2 3 4 7 6 5 8
1 2 3 4 7 6 5 8 9
1 2 3 4 7 6 5 8 9 10
1 2 3 4 7 10 9 8 5 6 11
1 2 3 4 7 10 9 8 5 6 11 12
1 2 3 4 7 6 5 12 11 8 9 10 13
1 2 3 4 7 6 13 10 9 8 11 12 5 14
1 2 3 4 7 6 13 10 9 8 11 12 5 14 15
1 2 3 4 7 6 5 12 11 8 15 14 9 10 13 16
1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14 17
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Elapsed time: 535 ms
</pre>

=={{header|Pascal}}==
==={{header|Free Pascal}}===
Simple backtracking.Precaltulated like [[Prime_triangle#Phix]] Can_Follow by checking for sum gets prime.
<syntaxhighlight lang="pascal">
program PrimePyramid;
{$IFDEF FPC}
{$MODE delphi}{$Optimization ON,ALL}{$CodeAlign proc=32}
{$IFEND}
const
MAX = 21;//max 8 different SumToPrime : array[0..MAX,0..7] of byte;
//MAX = 57;//max 16 different SumToPrime : array[0..MAX,0..15] of byte;
cMaxAlign32 = (((MAX-1)DIV 32)+1)*32-1;//MAX > 0
type
tPrimeRange = set of 0..127;
var
SetOfPrimes :tPrimeRange =[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,
53,59,61,67,71,73,79,83,89,97,101,103,107,
109,113,127];

SumToPrime : array[0..cMaxAlign32,0..7] of byte;
// SumToPrime : array[0..MAX,0..15] of byte;
SumToPrimeMaxIdx,
SumMaxIdx,
Solution,
FirstSolution : array[0..cMaxAlign32] of byte;

free : array[0..cMaxAlign32] of boolean;

maxused : integer;
digitcount,SolCount : integer;

procedure InitSumToPrime;
var
i,j,idx : integer;
begin
For i := 1 to MAX do
Begin
idx := 0;
For j := 1 to MAX do
If (i+j) in SetOfPrimes then
Begin
SumToPrime[i,idx] := j;
inc(idx);
end;
SumToPrimeMaxIdx[i] := idx;
end;
end;

procedure InitFree(maxused : integer);
var
i,j : Integer;
begin
For i := 0 to 1 do
Free[i] := false;
For i := 2 to maxused-1 do
Free[i] := true;
For i := maxused to MAX do
Free[i] := false;
// search maxidx of max neighour sum to prime
For i := 1 to maxused-1 do
begin
j := SumToPrimeMaxIdx[i]-1;
while SumToPrime[i,j] > maxused-1 do
j -= 1;
SumMaxIdx[i] := j+1;
end;
end;

procedure CountSolution(digit:integer);
begin
// check if maxused can follow
if (digit+maxused) in SetOfPrimes then
Begin
if solcount = 0 then
FirstSolution := Solution;
inc(solCount);
end;
end;

procedure checkDigits(digit:integer);
var
idx,nextDigit: integer;
begin
idx := 0;
repeat
nextDigit := SumToPrime[digit,idx];
if Free[nextdigit] then
Begin
Solution[digitcount] := nextDigit;
dec(digitcount);
IF digitcount = 0 then
CountSolution(nextDigit);
free[nextdigit]:= false;
checkDigits(nextdigit);
inc(digitcount);
free[nextdigit]:= true;
end;
inc(idx);
until idx >= SumMaxIdx[digit];
end;

var
i,j : integer;
Begin
InitSumToPrime;
writeln('number| count| first solution');
writeln(' 2| 1| 1 2');
For i := 3 to 20 do
Begin
maxused := i;
InitFree(i);
digitcount := i-2;
solCount := 0;
checkDigits(1);
write(i:4,'|',solcount:10,'| 1');
For j := i-2 downto 1 do
write( FirstSolution[j]:3);
writeln(i:3);
end;
end.
</syntaxhighlight>
{{out|@TIO.RUN}}
<pre>
number| count| first solution
2| 1| 1 2
3| 1| 1 2 3
4| 1| 1 2 3 4
5| 1| 1 4 3 2 5
6| 1| 1 4 3 2 5 6
7| 2| 1 4 3 2 5 6 7
8| 4| 1 2 3 4 7 6 5 8
9| 7| 1 2 3 4 7 6 5 8 9
10| 24| 1 2 3 4 7 6 5 8 9 10
11| 80| 1 2 3 4 7 10 9 8 5 6 11
12| 216| 1 2 3 4 7 10 9 8 5 6 11 12
13| 648| 1 2 3 4 7 6 5 12 11 8 9 10 13
14| 1304| 1 2 3 4 7 6 13 10 9 8 11 12 5 14
15| 3392| 1 2 3 4 7 6 13 10 9 8 11 12 5 14 15
16| 13808| 1 2 3 4 7 6 5 12 11 8 15 14 9 10 13 16
17| 59448| 1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14 17
18| 155464| 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
19| 480728| 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
20| 1588162| 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20
Real time: 1.827 s User time: 1.794 s Sys. time: 0.021 s CPU share: 99.36 %
@home: real 0m0,679s</pre>
=={{header|Perl}}==
{{trans|Raku}}
{{libheader|ntheory}}
<syntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
use ntheory 'is_prime';
use List::MoreUtils qw(zip slideatatime);
use Algorithm::Combinatorics qw(permutations);

say '1 2';

my @count = (0, 0, 1);

for my $n (3..17) {
my @even_nums = grep { 0 == $_ % 2 } 2..$n-1;
my @odd_nums = grep { 1 == $_ % 2 } 3..$n-1;
for my $e (permutations [@even_nums]) {
next if $$e[0] == 8 or $$e[0] == 14;
my $nope = 0;
for my $o (permutations [@odd_nums]) {
my @list = (zip(@$e, @$o), $n); # 'zip' makes a list with a gap if more evens than odds
splice @list, -2, -1 if not defined $list[-2]; # in which case splice out 'undef' in next-to-last position
my $it = slideatatime(1, 2, @list);
while ( my @rr = $it->() ) {
last unless defined $rr[1];
$nope++ and last unless is_prime $rr[0]+$rr[1];
}
unless ($nope) {
say '1 ' . join ' ', @list unless $count[$n];
$count[$n]++;
}
$nope = 0;
}
}
}

say "\n" . join ' ', @count[2..$#count];</syntaxhighlight>
{{out}}
<pre>1 2
1 2 3
1 2 3 4
1 4 3 2 5
1 4 3 2 5 6
1 4 3 2 5 6 7
1 2 3 4 7 6 5 8
1 2 3 4 7 6 5 8 9
1 2 3 4 7 6 5 8 9 10
1 2 3 4 9 10 7 6 5 8 11
1 2 3 4 9 10 7 6 5 8 11 12
1 2 3 4 7 6 5 12 11 8 9 10 13
1 2 3 4 13 6 11 8 9 10 7 12 5 14
1 2 3 4 13 6 11 8 9 10 7 12 5 14 15
1 2 3 4 13 6 11 8 9 10 7 12 5 14 15 16
1 2 15 4 13 6 11 8 9 10 3 16 7 12 5 14 17

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448</pre>


=={{header|Phix}}==
=={{header|Phix}}==
{{libheader|Phix/online}}
{{libheader|Phix/online}}
Not sure this counts as particularly clever but by the sound of things it's quite a bit faster than the other entries so far. &#128526;<br> You can run this online [http://phix.x10.mx/p2js/prime_triangles.htm here] (expect a blank screen for about 42s).
Not sure this counts as particularly clever but by the sound of things it's quite a bit faster than the other entries so far. &#128526;<br> You can run this online [http://phix.x10.mx/p2js/prime_triangles.htm here] (expect a blank screen for about 24s).
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">can_follow</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">avail</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">arrang</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">can_follow</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">arrang</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">bFirst</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">bFirst</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
Line 818: Line 1,591:
<span style="color: #008080;">else</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000080;font-style:italic;">-- as per talk page, we only need to examine odd
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
-- numbers following an even number & vice versa</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">avail</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">and</span> <span style="color: #000000;">can_follow</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ad</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">avail</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">done</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">arrang</span><span style="color: #0000FF;">[</span><span style="color: #000000;">done</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ai</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">arrang</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">can_follow</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ad</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ai</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">aid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">arrang</span><span style="color: #0000FF;">[</span><span style="color: #000000;">done</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">arrang</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">aid</span>
<span style="color: #000000;">arrang</span><span style="color: #0000FF;">[</span><span style="color: #000000;">done</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ai</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ptrs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">done</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ptrs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">done</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">avail</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #000000;">arrang</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ai</span>
<span style="color: #000000;">arrang</span><span style="color: #0000FF;">[</span><span style="color: #000000;">done</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">aid</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
Line 837: Line 1,615:
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">avail</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reinstate</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">},{</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">arrang</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">arrang</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reinstate</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">bFirst</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #000000;">bFirst</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ptrs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ptrs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
Line 846: Line 1,623:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">))</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 869: Line 1,646:
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
"15.5s"
"9.7s"
</pre>

=={{header|Python}}==
<syntaxhighlight lang="python">

from numpy import array
# for Rosetta Code by MG - 20230312
def is_prime(n: int) -> bool:
assert n < 64
return ((1 << n) & 0x28208a20a08a28ac) != 0

def prime_triangle_row(a: array, start: int, length: int) -> bool:
if length == 2:
return is_prime(a[0] + a[1])
for i in range(1, length - 1, 1):
if is_prime(a[start] + a[start + i]):
a[start + i], a[start + 1] = a[start + 1], a[start + i]
if prime_triangle_row(a, start + 1, length - 1):
return True
a[start + i], a[start + 1] = a[start + 1], a[start + i]
return False

def prime_triangle_count(a: array, start: int, length: int) -> int:
count: int = 0
if length == 2:
if is_prime(a[start] + a[start + 1]):
count += 1
else:
for i in range(1, length - 1, 1):
if is_prime(a[start] + a[start + i]):
a[start + i], a[start + 1] = a[start + 1], a[start + i]
count += prime_triangle_count(a, start + 1, length - 1)
a[start + i], a[start + 1] = a[start + 1], a[start + i]
return count

def print_row(a: array):
if a == []:
return
print("%2d"% a[0], end=" ")
for x in a[1:]:
print("%2d"% x, end=" ")
print()

for n in range(2, 21):
tr: array = [_ for _ in range(1, n + 1)]
if prime_triangle_row(tr, 0, n):
print_row(tr)
print()
for n in range(2, 21):
tr: array = [_ for _ in range(1, n + 1)]
if n > 2:
print(" ", end="")
print(prime_triangle_count(tr, 0, n), end="")
print()
</syntaxhighlight>

{{out}}
<pre>
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 4 3 2 5 6
1 4 3 2 5 6 7
1 2 3 4 7 6 5 8
1 2 3 4 7 6 5 8 9
1 2 3 4 7 6 5 8 9 10
1 2 3 4 7 6 5 8 9 10 11
1 2 3 4 7 10 9 8 5 6 11 12
1 2 3 4 7 6 5 12 11 8 9 10 13
1 2 3 4 7 6 5 12 11 8 9 10 13 14
1 2 3 4 7 6 13 10 9 8 11 12 5 14 15
1 2 3 4 7 6 5 12 11 8 15 14 9 10 13 16
1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14 17
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
</pre>
</pre>


Line 875: Line 1,731:
Limit the upper threshold a bit to avoid multiple hours of pointless calculations. Even just up to 17 takes over 20 minutes.
Limit the upper threshold a bit to avoid multiple hours of pointless calculations. Even just up to 17 takes over 20 minutes.


<lang perl6>my @count = 0, 0, 1;
<syntaxhighlight lang="raku" line>my @count = 0, 0, 1;
my $lock = Lock.new;
my $lock = Lock.new;
put (1,2);
put (1,2);
Line 899: Line 1,755:
}
}
}
}
put "\n", @count[2..*];</lang>
put "\n", @count[2..*];</syntaxhighlight>
{{out}}
{{out}}
<pre>1 2
<pre>1 2
Line 922: Line 1,778:


=={{header|Rust}}==
=={{header|Rust}}==
<lang rust>fn is_prime(n: u32) -> bool {
<syntaxhighlight lang="rust">fn is_prime(n: u32) -> bool {
assert!(n < 64);
assert!(n < 64);
((1u64 << n) & 0x28208a20a08a28ac) != 0
((1u64 << n) & 0x28208a20a08a28ac) != 0
Line 931: Line 1,787:
return is_prime(a[0] + a[1]);
return is_prime(a[0] + a[1]);
}
}
for i in 1..a.len() - 1 {
for i in (1..a.len() - 1).step_by(2) {
if is_prime(a[0] + a[i]) {
if is_prime(a[0] + a[i]) {
a.swap(i, 1);
a.swap(i, 1);
Line 950: Line 1,806:
}
}
} else {
} else {
for i in 1..a.len() - 1 {
for i in (1..a.len() - 1).step_by(2) {
if is_prime(a[0] + a[i]) {
if is_prime(a[0] + a[i]) {
a.swap(i, 1);
a.swap(i, 1);
Line 992: Line 1,848:
let time = start.elapsed();
let time = start.elapsed();
println!("\nElapsed time: {} milliseconds", time.as_millis());
println!("\nElapsed time: {} milliseconds", time.as_millis());
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,018: Line 1,874:
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162


Elapsed time: 711 milliseconds
Elapsed time: 674 milliseconds
</pre>
</pre>


=={{header|Swift}}==
=={{header|Swift}}==
<lang swift>import Foundation
<syntaxhighlight lang="swift">import Foundation


func isPrime(_ n: Int) -> Bool {
func isPrime(_ n: Int) -> Bool {
Line 1,031: Line 1,887:
}
}


func primeTriangleRow(_ a: inout ArraySlice<Int>) -> Bool {
func primeTriangleRow(_ a: inout [Int], start: Int, length: Int) -> Bool {
let start = a.startIndex
if length == 2 {
let end = a.endIndex
if a.count == 2 {
return isPrime(a[start] + a[start + 1])
return isPrime(a[start] + a[start + 1])
}
}
for i in start + 1..<end - 1 {
for i in stride(from: 1, to: length - 1, by: 2) {
if isPrime(a[start] + a[i]) {
let index = start + i
a.swapAt(i, start + 1)
if isPrime(a[start] + a[index]) {
if primeTriangleRow(&a[start + 1..<end]) {
a.swapAt(index, start + 1)
if primeTriangleRow(&a, start: start + 1, length: length - 1) {
return true
return true
}
}
a.swapAt(i, start + 1)
a.swapAt(index, start + 1)
}
}
}
}
Line 1,049: Line 1,904:
}
}


func primeTriangleCount(_ a: inout ArraySlice<Int>) -> Int {
func primeTriangleCount(_ a: inout [Int], start: Int, length: Int) -> Int {
let start = a.startIndex
let end = a.endIndex
var count = 0
var count = 0
if a.count == 2 {
if length == 2 {
if isPrime(a[start] + a[start + 1]) {
if isPrime(a[start] + a[start + 1]) {
count += 1
count += 1
}
}
} else {
} else {
for i in start + 1..<end - 1 {
for i in stride(from: 1, to: length - 1, by: 2) {
if isPrime(a[start] + a[i]) {
let index = start + i
a.swapAt(i, start + 1)
if isPrime(a[start] + a[index]) {
count += primeTriangleCount(&a[start + 1..<end])
a.swapAt(index, start + 1)
a.swapAt(i, start + 1)
count += primeTriangleCount(&a, start: start + 1, length: length - 1)
a.swapAt(index, start + 1)
}
}
}
}
Line 1,079: Line 1,933:
print()
print()
}
}

let startTime = CFAbsoluteTimeGetCurrent()


for n in 2...20 {
for n in 2...20 {
var a = Array(1...n)
var a = Array(1...n)
if primeTriangleRow(&a[...]) {
if primeTriangleRow(&a, start: 0, length: n) {
printRow(a)
printRow(a)
}
}
Line 1,093: Line 1,949:
print(" ", terminator: "")
print(" ", terminator: "")
}
}
print("\(primeTriangleCount(&a[...]))", terminator: "")
print("\(primeTriangleCount(&a, start: 0, length: n))", terminator: "")
}
}
print()</lang>
print()

let endTime = CFAbsoluteTimeGetCurrent()
print("\nElapsed time: \(endTime - startTime) seconds")</syntaxhighlight>


{{out}}
{{out}}
Line 1,120: Line 1,979:


1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
</pre>


Elapsed time: 1.0268970727920532 seconds
=={{header|Visual Basic .NET}}==
{{Trans|ALGOL 68}}
<lang vbnet>Option Strict On
Option Explicit On

Imports System.IO

''' <summary>Find solutions to the "Prime Triangle" - a triangle of numbers that sum to primes.</summary>
Module vMain

Public Const maxNumber As Integer = 20 ' Largest number we will consider.
Dim prime(2 * maxNumber) As Boolean ' prime sieve.
Dim primePair(maxNumber, maxNumber) As Boolean ' Table of numbers that sum to a prime.

''' <returns>The next number that can follow i or 0 if there isn't one.</returns>
Public Function findNext(ByVal i As Integer, ByVal n As Integer, ByVal current As Integer, ByVal used() As Boolean) As Integer
Dim result As Integer = current + 2
' The numbers must alternate between even and odd in order for the sum to be prime.
If i Mod 2 = 0 And result = 2 Then
result = 3
End If
Do While result < n AndAlso (Not primePair(i, result) Or used(result))
result += 2
Loop
If result >= n Then
result = 0
End If
Return result
End Function

''' <returns>The number of possible arrangements of the integers for a row in the prime triangle.</returns>
Public Function countArrangements(ByVal n As Integer, ByVal printSolution As Boolean ) As Integer
If n < 2 Then ' No solutions for n < 2.
Return 0
ElseIf n < 4 Then
' For 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3.
If printSolution Then
For i As Integer = 1 To n
Console.Out.Write(i.ToString.PadLeft(3))
Next i
Console.Out.WriteLine()
End If
Return 1
Else
' 4 or more - must find the solutions.
Dim used(n) As Boolean
Dim number(n) As Integer
' The triangle row must have 1 in the leftmost and n in the rightmost elements.
number(1) = 1
used(1) = True
number(n) = n
used(n) = True
' Find the intervening numbers and count the solutions.
Dim count As Integer = 0
Dim p As Integer = 2
Do While p < n
Dim pn As Integer = number(p - 1)
Dim [next] As Integer = findNext(pn, n, number(p), used)
If p = n - 1 Then
' We are at the final number before n.
Do While If([next] = 0, False, Not primePair([next], n))
[next] = findNext(pn, n, [next], used)
Loop
End If
If [next] <> 0 Then
' have a/another number that can appear at p.
used(number(p)) = False
used([next]) = True
number(p) = [next]
If p < n - 1 Then
' Haven't found all the intervening digits yet.
p += 1
number(p) = 0
Else
' Found a solution.
count += 1
If count = 1 And printSolution Then
For i As Integer = 1 To n
Console.Out.Write(number(i).ToString.PadLeft(3))
Next i
Console.Out.WriteLine()
End If
' Backtrack for more solutions.
used(number(p)) = False
number(p) = 0
p -= 1
End If
ElseIf p <= 2 Then
' No more solutions.
p = n
Else
' Can't find a number for this position, backtrack.
used(number(p)) = False
number(p) = 0
p -= 1
End If
Loop
Return count
End If
End Function

Public Sub Main
prime(2) = True
For i As Integer = 3 To UBound(prime) Step 2
prime(i) = True
Next i
For i As Integer = 3 To Convert.ToInt32(Math.Floor(Math.Sqrt(Ubound(prime)))) Step 2
If prime(i) Then
For s As Integer = i * i To Ubound(prime) Step i + i
prime(s) = False
Next s
End If
Next i
For a As Integer = 1 To maxNumber
primePair(a, 1) = False
For b As Integer = 2 To maxNumber
primePair(a, b) = prime(a + b)
Next b
primePair(a, a) = False
Next a

Dim arrangements(maxNumber) As Integer
For n As Integer = 2 To UBound(arrangements)
arrangements(n) = countArrangements(n, True)
Next n
For n As Integer = 2 To UBound(arrangements)
Console.Out.Write(" " & arrangements(n))
Next n
Console.Out.WriteLine()

End Sub

End Module</lang>
{{out}}
<pre>
1 2
1 2 3
1 2 3 4
1 4 3 2 5
1 4 3 2 5 6
1 4 3 2 5 6 7
1 2 3 4 7 6 5 8
1 2 3 4 7 6 5 8 9
1 2 3 4 7 6 5 8 9 10
1 2 3 4 7 10 9 8 5 6 11
1 2 3 4 7 10 9 8 5 6 11 12
1 2 3 4 7 6 5 12 11 8 9 10 13
1 2 3 4 7 6 13 10 9 8 11 12 5 14
1 2 3 4 7 6 13 10 9 8 11 12 5 14 15
1 2 3 4 7 6 5 12 11 8 15 14 9 10 13 16
1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14 17
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
</pre>
</pre>


Line 1,282: Line 1,986:
{{trans|Phix}}
{{trans|Phix}}
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
Takes around 18.7 seconds which is fine for Wren.
{{libheader|Wren-ioutil}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
Takes around 57.3 seconds which is fine for Wren.
<lang ecmascript>import "./fmt" for Fmt
import "./ioutil" for Output


var canFollow = []
var canFollow = []
var avail = []
var arrang = []
var arrang = []
var bCount = false
var bFirst = true


var pmap = {}
var pmap = {}
Line 1,302: Line 2,003:
if (n - done <= 1) {
if (n - done <= 1) {
if (canFollow[ad-1][n-1]) {
if (canFollow[ad-1][n-1]) {
if (!bCount) Fmt.print("$2d", arrang)
if (bFirst) {
Fmt.print("$2d", arrang)
bFirst = false
}
res = res + 1
res = res + 1
}
}
} else {
} else {
done = done + 1
done = done + 1
for (i in 1..n-2) {
var i = done - 1
if (avail[i] && canFollow[ad-1][i]) {
while (i <= n-2) {
avail[i] = false
var ai = arrang[i]
arrang[done-1] = i+1
if (canFollow[ad-1][ai-1]) {
arrang.swap(i, done-1)
res = ptrs.call(res, n, done)
res = ptrs.call(res, n, done)
if (!bCount && res != 0) return res
arrang.swap(i, done-1)
avail[i] = true
}
}
i = i + 2
}
}
}
}
Line 1,326: Line 2,031:
for (j in 0...n) canFollow[i][j] = pmap.containsKey(i+j+2)
for (j in 0...n) canFollow[i][j] = pmap.containsKey(i+j+2)
}
}
avail = List.filled(n, true)
bFirst = true
avail[0] = avail[n-1] = false
arrang = (1..n).toList
arrang = List.filled(n, 0)
arrang[0] = 1
arrang[n-1] = n
return ptrs.call(0, n, 1)
return ptrs.call(0, n, 1)
}
}


var counts = []
for (i in 2..20) primeTriangle.call(i)
for (i in 2..20) {
counts.add(primeTriangle.call(i))
}
System.print()
System.print()
System.print(counts.join(" "))</syntaxhighlight>
bCount = true
for (i in 2..20) Output.fwrite("%(primeTriangle.call(i)) ")
System.print()</lang>


{{out}}
{{out}}

Latest revision as of 01:24, 3 March 2024

Task
Prime triangle
You are encouraged to solve this task according to the task description, using any language you may know.

You will require a function f which when given an integer S will return a list of the arrangements of the integers 1 to S such that g1=1 gS=S and generally for n=1 to n=S-1 gn+gn+1 is prime. S=1 is undefined. For S=2 to S=20 print f(S) to form a triangle. Then again for S=2 to S=20 print the number of possible arrangements of 1 to S meeting these requirements.


See also


ALGOL 68

Iterative, backtracking solution - similar to the Phix and Wren versions but not recursive. Counts the arrangements but does not store them.

Works with: ALGOL 68G version Any - tested with release 2.8.3.win32

As Algol 68G under Windows is fully interpreted, a reduced number of rows is produced.

BEGIN # find solutions to the "Prime Triangle" - a triangle of numbers that sum to primes #
    INT max number = 18; # largest number we will consider #
    # construct a primesieve and from that a table of pairs of numbers whose sum is prime #
    [ 0 : 2 * max number ]BOOL prime;
    prime[ 0 ] := prime[ 1 ] := FALSE;
    prime[ 2 ] := TRUE;
    FOR i FROM 3 BY 2 TO UPB prime DO prime[ i ] := TRUE  OD;
    FOR i FROM 4 BY 2 TO UPB prime DO prime[ i ] := FALSE OD;
    FOR i FROM 3 BY 2 TO ENTIER sqrt( UPB prime ) DO
        IF prime[ i ] THEN
            FOR s FROM i * i BY i + i TO UPB prime DO prime[ s ] := FALSE OD
        FI
    OD;
    # returns the number of possible arrangements of the integers for a row in the prime triangle #
    PROC count arrangements = ( INT n )INT:
         IF   n < 2 THEN # no solutions for n < 2 # 0
         ELIF n < 4 THEN
             # for 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3 #
             FOR i TO n DO print( ( whole( i, -3 ) ) ) OD; print( ( newline ) );
             1
         ELSE
             # 4 or more - must find the solutions #
             BOOL print solution := TRUE;
             [ 0 : n ]BOOL used;
             [ 0 : n ]INT  number;
             # the triangle row must have 1 in the leftmost and n in the rightmost elements #
             # the numbers must alternate between even and odd in order for the sum to be prime #
             FOR i FROM 0 TO n DO
                 used[   i ] := FALSE;
                 number[ i ] := i MOD 2
             OD;
             used[   1 ] := TRUE;
             number[ n ] := n;
             used[   n ] := TRUE;
             # find the intervening numbers and count the solutions #
             INT count := 0;
             INT p     := 2;
             WHILE p > 0 DO
                 INT p1      = number[ p - 1 ];
                 INT current = number[ p     ];
                 INT next   := current + 2;
                 WHILE IF next >= n THEN FALSE ELSE NOT prime[ p1 + next ] OR used[ next ] FI DO
                     next +:= 2
                 OD;
                 IF next >= n THEN next := 0 FI;
                 IF p = n - 1 THEN
                     # we are at the final number before n #
                     # it must be the final even/odd number preceded by the final odd/even number #
                     IF next /= 0 THEN
                         # possible solution #
                         IF prime[ next + n ] THEN
                             # found a solution #
                             count +:= 1;
                             IF print solution THEN
                                 FOR i TO n - 2 DO
                                     print( ( whole( number[ i ], -3 ) ) )
                                 OD;
                                 print( ( whole( next, -3 ), whole( n, - 3 ), newline ) );
                                 print solution := FALSE
                             FI
                         FI;
                         next := 0
                     FI;
                     # backtrack for more solutions #
                     p -:= 1
                     # here will be a further backtrack as next is 0 ( there could only be one possible number at p - 1 ) #
                 FI;
                 IF next /= 0 THEN
                     # have a/another number that can appear at p #
                     used[ current ] := FALSE;
                     used[    next ] := TRUE;
                     number[     p ] := next;
                     p +:= 1
                 ELIF p <= 2 THEN
                     # no more solutions #
                     p := 0
                 ELSE
                     # can't find a number for this position, backtrack #
                     used[ number[ p ] ] := FALSE;
                     number[       p   ] := p MOD 2;
                     p -:= 1
                 FI
             OD;
             count
         FI # count arrangements # ;
    [ 2 : max number ]INT arrangements;
    FOR n FROM LWB arrangements TO UPB arrangements DO
        arrangements[ n ] := count arrangements( n )
    OD;
    FOR n FROM LWB arrangements TO UPB arrangements DO
        print( ( " ", whole( arrangements[ n ], 0 ) ) )
    OD;
    print( ( newline ) )        
END
Output:
  1  2
  1  2  3
  1  2  3  4
  1  4  3  2  5
  1  4  3  2  5  6
  1  4  3  2  5  6  7
  1  2  3  4  7  6  5  8
  1  2  3  4  7  6  5  8  9
  1  2  3  4  7  6  5  8  9 10
  1  2  3  4  7 10  9  8  5  6 11
  1  2  3  4  7 10  9  8  5  6 11 12
  1  2  3  4  7  6  5 12 11  8  9 10 13
  1  2  3  4  7  6 13 10  9  8 11 12  5 14
  1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
  1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
  1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
 1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464

BASIC

FreeBASIC

Translation of: Visual Basic .NET
Dim Shared As Uinteger maxNumber = 20 ' Largest number we will consider.
Dim Shared As Uinteger prime(2 * maxNumber) ' prime sieve.

Function countArrangements(Byval n As Uinteger) As Uinteger
    Dim As Uinteger i
    If n < 2 Then ' No solutions for n < 2.
        Return 0
    Elseif n < 4 Then 
        ' For 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3.
        For i = 1 To n
            Print Using "###"; i;
        Next i
        Print
        Return 1
    Else
        ' 4 or more - must find the solutions.
        Dim As Boolean printSolution = True
        Dim As Boolean used(n)
        Dim As Uinteger number(n)
        ' The triangle row must have 1 in the leftmost and n in the rightmost elements.
        ' The numbers must alternate between even and odd in order for the sums to be prime.
        For i = 0 To n - 1
            number(i) = i Mod 2
        Next i
        used(1) = True
        number(n) = n
        used(n) = True
        ' Find the intervening numbers and count the solutions.
        Dim As Uinteger count = 0
        Dim As Uinteger p = 2
        Do While p > 0
            Dim As Uinteger p1 = number(p - 1)
            Dim As Uinteger current = number(p)
            Dim As Uinteger sgte = current + 2
            Do While sgte < n Andalso (Not prime(p1 + sgte) Or used(sgte))
                sgte += 2
            Loop
            If sgte >= n Then
                sgte = 0
            End If
            If p = n - 1 Then
                ' We are at the final number before n.
                ' It must be the final even/odd number preceded by the final odd/even number.
                If sgte <> 0 Then
                    ' Possible solution.
                    If prime(sgte + n) Then
                        ' Found a solution.
                        count += 1
                        If printSolution Then
                            For i = 1 To n - 2
                                Print Using "###"; number(i);
                            Next i
                            Print Using "###"; sgte; n
                            printSolution = False
                        End If
                    End If
                    sgte = 0
                End If
                ' Backtrack for more solutions.
                p -= 1
                ' There will be a further backtrack as next is 0 ( there could only be one possible number at p - 1 ).
            End If
            If sgte <> 0 Then
                ' have a/another number that can appear at p.
                used(current) = False
                used(sgte) = True
                number(p) = sgte
                ' Haven't found all the intervening digits yet.
                p += 1
            Elseif p <= 2 Then
                ' No more solutions.
                p = 0
            Else
                ' Can't find a number for this position, backtrack.
                used(number(p)) = False
                number(p) = p Mod 2
                p -= 1
            End If
        Loop
        Return count
    End If
End Function

Dim As Integer i, s, n
prime(2) = True
For i = 3 To Ubound(prime) Step  2
    prime(i) = True
Next i
For i = 3 To Cint(Sqr(Ubound(prime))) Step 2
    If prime(i) Then
        For s = i * i To Ubound(prime) Step i + i
            prime(s) = False
        Next s
    End If
Next i

Dim As Integer arrangements(maxNumber)
For n = 2 To Ubound(arrangements)
    arrangements(n) = countArrangements(n)
Next n
For n = 2 To Ubound(arrangements)
    Print arrangements(n);
Next n
Print

Sleep
Output:
Same as Visual Basic .NET entry.

Visual Basic .NET

Translation of: ALGOL 68
Option Strict On
Option Explicit On

Imports System.IO

''' <summary>Find solutions to the "Prime Triangle" - a triangle of numbers that sum to primes.</summary>
Module vMain

    Public Const maxNumber As Integer = 20 ' Largest number we will consider.
    Dim prime(2 * maxNumber) As Boolean    ' prime sieve.

    ''' <returns>The number of possible arrangements of the integers for a row in the prime triangle.</returns>
    Public Function countArrangements(ByVal n As Integer) As Integer
        If n < 2 Then ' No solutions for n < 2.
            Return 0
        ElseIf n < 4 Then 
            ' For 2 and 3. there is only 1 solution: 1, 2 and 1, 2, 3.
            For i As Integer = 1 To n
                Console.Out.Write(i.ToString.PadLeft(3))
            Next i
            Console.Out.WriteLine()
            Return 1
        Else
            ' 4 or more - must find the solutions.
            Dim printSolution As Boolean = true
            Dim used(n) As Boolean
            Dim number(n) As Integer
            ' The triangle row must have 1 in the leftmost and n in the rightmost elements.
            ' The numbers must alternate between even and odd in order for the sums to be prime.
            For i As Integer = 0 To n - 1
                number(i) = i Mod 2
            Next i
            used(1) = True
            number(n) = n
            used(n) = True
            ' Find the intervening numbers and count the solutions.
            Dim count As Integer = 0
            Dim p As Integer = 2
            Do While p > 0
                Dim p1 As Integer = number(p - 1)
                Dim current As Integer = number(p)
                Dim [next] As Integer = current + 2
                Do While [next] < n AndAlso (Not prime(p1 + [next]) Or used([next]))
                    [next] += 2
                Loop
                If [next] >= n Then
                    [next] = 0
                End If
                If p = n - 1 Then
                    ' We are at the final number before n.
                    ' It must be the final even/odd number preceded by the final odd/even number.
                    If [next] <> 0 Then
                        ' Possible solution.
                        If prime([next] + n) Then
                            ' Found a solution.
                            count += 1
                            If printSolution Then
                                For i As Integer = 1 To n - 2
                                     Console.Out.Write(number(i).ToString.PadLeft(3))
                                Next i
                                Console.Out.WriteLine([next].ToString.PadLeft(3) & n.ToString.PadLeft(3))
                                printSolution = False
                            End If
                        End If
                        [next] = 0
                    End If
                    ' Backtrack for more solutions.
                    p -= 1
                    ' There will be a further backtrack as next is 0 ( there could only be one possible number at p - 1 ).
                End If
                If [next] <> 0 Then
                    ' have a/another number that can appear at p.
                    used(current) = False
                    used([next]) = True
                    number(p) = [next]
                    ' Haven't found all the intervening digits yet.
                    p += 1
                ElseIf p <= 2 Then
                    ' No more solutions.
                    p = 0
                Else
                    ' Can't find a number for this position, backtrack.
                    used(number(p)) = False
                    number(p) = p Mod 2
                    p -= 1
                End If
            Loop
            Return count
        End If
    End Function

    Public Sub Main
        prime(2) = True
        For i As Integer = 3 To UBound(prime) Step  2
            prime(i) = True
        Next i
        For i As Integer = 3 To Convert.ToInt32(Math.Floor(Math.Sqrt(Ubound(prime)))) Step 2
            If prime(i) Then
                For s As Integer = i * i To Ubound(prime) Step i + i
                    prime(s) = False
                Next s
            End If
        Next i

        Dim  arrangements(maxNumber) As Integer
        For n As Integer = 2 To UBound(arrangements)
            arrangements(n) = countArrangements(n)
        Next n
        For n As Integer = 2 To UBound(arrangements)
            Console.Out.Write(" " & arrangements(n))
        Next n
        Console.Out.WriteLine()

    End Sub

End Module
Output:
  1  2
  1  2  3
  1  2  3  4
  1  4  3  2  5
  1  4  3  2  5  6
  1  4  3  2  5  6  7
  1  2  3  4  7  6  5  8
  1  2  3  4  7  6  5  8  9
  1  2  3  4  7  6  5  8  9 10
  1  2  3  4  7 10  9  8  5  6 11
  1  2  3  4  7 10  9  8  5  6 11 12
  1  2  3  4  7  6  5 12 11  8  9 10 13
  1  2  3  4  7  6 13 10  9  8 11 12  5 14
  1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
  1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
  1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20
 1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

C

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <time.h>

bool is_prime(unsigned int n) {
    assert(n < 64);
    static bool isprime[] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0,
                             0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
                             0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1,
                             0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0};
    return isprime[n];
}

void swap(unsigned int* a, size_t i, size_t j) {
    unsigned int tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}

bool prime_triangle_row(unsigned int* a, size_t length) {
    if (length == 2)
        return is_prime(a[0] + a[1]);
    for (size_t i = 1; i + 1 < length; i += 2) {
        if (is_prime(a[0] + a[i])) {
            swap(a, i, 1);
            if (prime_triangle_row(a + 1, length - 1))
                return true;
            swap(a, i, 1);
        }
    }
    return false;
}

int prime_triangle_count(unsigned int* a, size_t length) {
    int count = 0;
    if (length == 2) {
        if (is_prime(a[0] + a[1]))
            ++count;
    } else {
        for (size_t i = 1; i + 1 < length; i += 2) {
            if (is_prime(a[0] + a[i])) {
                swap(a, i, 1);
                count += prime_triangle_count(a + 1, length - 1);
                swap(a, i, 1);
            }
        }
    }
    return count;
}

void print(unsigned int* a, size_t length) {
    if (length == 0)
        return;
    printf("%2u", a[0]);
    for (size_t i = 1; i < length; ++i)
        printf(" %2u", a[i]);
    printf("\n");
}

int main() {
    clock_t start = clock();
    for (unsigned int n = 2; n < 21; ++n) {
        unsigned int a[n];
        for (unsigned int i = 0; i < n; ++i)
            a[i] = i + 1;
        if (prime_triangle_row(a, n))
            print(a, n);
    }
    printf("\n");
    for (unsigned int n = 2; n < 21; ++n) {
        unsigned int a[n];
        for (unsigned int i = 0; i < n; ++i)
            a[i] = i + 1;
        if (n > 2)
            printf(" ");
        printf("%d", prime_triangle_count(a, n));
    }
    printf("\n");
    clock_t end = clock();
    double duration = (end - start + 0.0) / CLOCKS_PER_SEC;
    printf("\nElapsed time: %f seconds\n", duration);
    return 0;
}
Output:
 1  2
 1  2  3
 1  2  3  4
 1  4  3  2  5
 1  4  3  2  5  6
 1  4  3  2  5  6  7
 1  2  3  4  7  6  5  8
 1  2  3  4  7  6  5  8  9
 1  2  3  4  7  6  5  8  9 10
 1  2  3  4  7 10  9  8  5  6 11
 1  2  3  4  7 10  9  8  5  6 11 12
 1  2  3  4  7  6  5 12 11  8  9 10 13
 1  2  3  4  7  6 13 10  9  8 11 12  5 14
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
 1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
 1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Elapsed time: 0.572986 seconds

Use bit patterns

Number combinations are all stored in bit positions here. The bpos() functions returns the position index of the least significant bit in an integer. This code gains some speed, at the cost of total loss of readability. On the plus side, it has some bit manipulation tricks that may be interesting to some.

#include <stdio.h>
#include <stdint.h>

#define GCC_ASM // use GCC's asm for i386. If it does not work, #undef it to use alternative func
typedef uint32_t uint;
typedef uint64_t ulong;

#define MASK 0xa08228828228a2bULL

#ifdef GCC_ASM

static inline uint
bpos(uint x)
{
	uint b;
	asm("bsf %0, %0" : "=r" (b): "0" (x));
	return b;
}

#else

static inline uint
bpos(uint x)
{
	static const uint bruijin[32] = {
		 0,  1, 28,  2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17,  4, 8, 
		31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18,  6, 11,  5, 10, 9
	};
	return bruijin[((uint)((x & -x) * 0x077CB531U)) >> 27];
}

#endif // GCC_ASM

int count(uint n, const uint s, uint avail)
{
	int cnt = 0;

	avail ^= s;
	if (--n)
		for (uint b = (uint)(MASK>>bpos(s)) & avail; b; b &= b-1)
			cnt += count(n, b&-b, avail);
	else
		return (MASK & s) != 0;

	return cnt;
}

int disp(uint n, const uint s, uint avail, int maxn, uint *seq)
{
	seq[n--] = s;
	if (!n) {
		if ((MASK & s)) {
			for (int i = 0; i < maxn; i++)
				printf(" %d", bpos(seq[i]) + 1);
			putchar('\n');
			return 1;
		}
	} else {
		for (uint b = (uint)(MASK>>bpos(s)) & (avail ^= s); b; b &= b-1)
			if (disp(n, b&-b, avail, maxn, seq))
				return 1;
	}
	return 0;
}

int chain(uint n, int count_only)
{
	const uint top = 1U<<(n - 1);
	const uint avail = 2*top - 2;

	if (count_only)
		return count(n - 1, top, avail);

	uint seq[32];
	seq[0] = 1;
	disp(n - 1, top, avail, n, seq);

	return 0;
}

int main(void)
{
	for (int n = 2; n < 21; n++)
		chain(n, 0);
	putchar('\n');

	for (int n = 2; n < 21; n++)
		printf("%d ", chain(n, 1));
	putchar('\n');

	return 0;
}
Output:
 1 2
 1 2 3
 1 2 3 4
 1 4 3 2 5
 1 4 3 2 5 6
 1 6 5 2 3 4 7
 1 4 7 6 5 2 3 8
 1 4 7 6 5 8 3 2 9
 1 6 7 4 9 8 5 2 3 10
 1 10 9 8 5 6 7 4 3 2 11
 1 10 9 8 11 6 7 4 3 2 5 12
 1 12 11 8 9 10 7 6 5 2 3 4 13
 1 12 11 8 9 10 13 4 7 6 5 2 3 14
 1 12 11 8 5 14 9 10 13 6 7 4 3 2 15
 1 12 11 8 15 14 9 10 13 4 7 6 5 2 3 16
 1 10 13 16 15 14 9 8 11 12 5 6 7 4 3 2 17
 1 12 17 14 15 16 13 10 9 8 11 6 7 4 3 2 5 18
 1 18 13 16 15 14 17 12 11 8 9 10 7 6 5 2 3 4 19
 1 18 19 10 13 16 15 14 17 12 11 8 9 4 7 6 5 2 3 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

C++

#include <cassert>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>

bool is_prime(unsigned int n) {
    assert(n > 0 && n < 64);
    return (1ULL << n) & 0x28208a20a08a28ac;
}

template <typename Iterator>
bool prime_triangle_row(Iterator begin, Iterator end) {
    if (std::distance(begin, end) == 2)
        return is_prime(*begin + *(begin + 1));
    for (auto i = begin + 1; i + 1 != end; ++i) {
        if (is_prime(*begin + *i)) {
            std::iter_swap(i, begin + 1);
            if (prime_triangle_row(begin + 1, end))
                return true;
            std::iter_swap(i, begin + 1);
        }
    }
    return false;
}

template <typename Iterator>
void prime_triangle_count(Iterator begin, Iterator end, int& count) {
    if (std::distance(begin, end) == 2) {
        if (is_prime(*begin + *(begin + 1)))
            ++count;
        return;
    }
    for (auto i = begin + 1; i + 1 != end; ++i) {
        if (is_prime(*begin + *i)) {
            std::iter_swap(i, begin + 1);
            prime_triangle_count(begin + 1, end, count);
            std::iter_swap(i, begin + 1);
        }
    }
}

template <typename Iterator>
void print(Iterator begin, Iterator end) {
    if (begin == end)
        return;
    auto i = begin;
    std::cout << std::setw(2) << *i++;
    for (; i != end; ++i)
        std::cout << ' ' << std::setw(2) << *i;
    std::cout << '\n';
}

int main() {
    auto start = std::chrono::high_resolution_clock::now();
    for (unsigned int n = 2; n < 21; ++n) {
        std::vector<unsigned int> v(n);
        std::iota(v.begin(), v.end(), 1);
        if (prime_triangle_row(v.begin(), v.end()))
            print(v.begin(), v.end());
    }
    std::cout << '\n';
    for (unsigned int n = 2; n < 21; ++n) {
        std::vector<unsigned int> v(n);
        std::iota(v.begin(), v.end(), 1);
        int count = 0;
        prime_triangle_count(v.begin(), v.end(), count);
        if (n > 2)
            std::cout << ' ';
        std::cout << count;
    }
    std::cout << '\n';
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> duration(end - start);
    std::cout << "\nElapsed time: " << duration.count() << " seconds\n";
}
Output:
 1  2
 1  2  3
 1  2  3  4
 1  4  3  2  5
 1  4  3  2  5  6
 1  4  3  2  5  6  7
 1  2  3  4  7  6  5  8
 1  2  3  4  7  6  5  8  9
 1  2  3  4  7  6  5  8  9 10
 1  2  3  4  7 10  9  8  5  6 11
 1  2  3  4  7 10  9  8  5  6 11 12
 1  2  3  4  7  6  5 12 11  8  9 10 13
 1  2  3  4  7  6 13 10  9  8 11 12  5 14
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
 1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
 1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Elapsed time: 0.636331 seconds

F#

This task uses Extensible Prime Generator (F#)

// Prime triangle. Nigel Galloway: April 12th., 2022
let     fN i (g,(e,l))=e|>Seq.map(fun n->let n=i n in (n::g,List.partition(i>>(=)n) l))
let rec fG n g=function 0->n|>Seq.map fst |x->fG(n|>Seq.collect(fN(if g then fst else snd)))(not g)(x-1)
let primeT row=fG [([1],([for g in {2..2..row-1} do if isPrime(g+1) then yield (1,g)],[for n in {3..2..row-1} do for g in {2..2..row-1} do if isPrime(n+g) then yield (n,g)]))] false (row-2)
                 |>Seq.filter(List.head>>(+)row>>isPrime)|>Seq.map(fun n->row::n|>List.rev)

{2..20}|>Seq.iter(fun n->(primeT>>Seq.head>>List.iter(printf "%3d"))n;printfn "");;
{2..20}|>Seq.iter(primeT>>Seq.length>>printf "%d "); printfn ""
Output:
  1  2
  1  2  3
  1  2  3  4
  1  4  3  2  5
  1  4  3  2  5  6
  1  4  3  2  5  6  7
  1  2  3  4  7  6  5  8
  1  2  3  4  7  6  5  8  9
  1  2  3  4  7  6  5  8  9 10
  1  2  3  4  7 10  9  8  5  6 11
  1  2  3  4  7 10  9  8  5  6 11 12
  1  2  3  4  7  6  5 12 11  8  9 10 13
  1  2  3  4  7  6 13 10  9  8 11 12  5 14
  1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
  1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
  1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Go

Takes about 0.64 seconds.

Translation of: Phix
package main

import "fmt"

var canFollow [][]bool
var arrang []int
var bFirst = true

var pmap = make(map[int]bool)

func init() {
    for _, i := range []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37} {
        pmap[i] = true
    }
}

func ptrs(res, n, done int) int {
    ad := arrang[done-1]
    if n-done <= 1 {
        if canFollow[ad-1][n-1] {
            if bFirst {
                for _, e := range arrang {
                    fmt.Printf("%2d ", e)
                }
                fmt.Println()
                bFirst = false
            }
            res++
        }
    } else {
        done++
        for i := done - 1; i <= n-2; i += 2 {
            ai := arrang[i]
            if canFollow[ad-1][ai-1] {
                arrang[i], arrang[done-1] = arrang[done-1], arrang[i]
                res = ptrs(res, n, done)
                arrang[i], arrang[done-1] = arrang[done-1], arrang[i]
            }
        }
    }
    return res
}

func primeTriangle(n int) int {
    canFollow = make([][]bool, n)
    for i := 0; i < n; i++ {
        canFollow[i] = make([]bool, n)
        for j := 0; j < n; j++ {
            _, ok := pmap[i+j+2]
            canFollow[i][j] = ok
        }
    }
    bFirst = true
    arrang = make([]int, n)
    for i := 0; i < n; i++ {
        arrang[i] = i + 1
    }
    return ptrs(0, n, 1)
}

func main() {
    counts := make([]int, 19)
    for i := 2; i <= 20; i++ {
        counts[i-2] = primeTriangle(i)
    }
    fmt.Println()
    for i := 0; i < 19; i++ {
        fmt.Printf("%d ", counts[i])
    }
    fmt.Println()
}
Output:
 1  2 
 1  2  3 
 1  2  3  4 
 1  4  3  2  5 
 1  4  3  2  5  6 
 1  4  3  2  5  6  7 
 1  2  3  4  7  6  5  8 
 1  2  3  4  7  6  5  8  9 
 1  2  3  4  7  6  5  8  9 10 
 1  2  3  4  7 10  9  8  5  6 11 
 1  2  3  4  7 10  9  8  5  6 11 12 
 1  2  3  4  7  6  5 12 11  8  9 10 13 
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 15 
 1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16 
 1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17 
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19 
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20 

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162 

J

Essentially, we're traversing a directed graph starting at 1, ending at y, with edges such that adjacent pairs sum to a prime number and with distinct intermediate values between 1 and y.

Implementation:

add_plink=: [:;{{ <y,"1 0 x #~ 1 p:+/|:(x=. x-. y),"0/{: y }}"1
prime_pair_seqs=: {{ y add_plink (2}.i.y) add_plink^:(y-2) 1 }}

Task example (displaying counts of number of valid sequences to the left, because that looks nice):

task=: {{
  for_j.2}.i.1+y do.
    N=. #seqs=. prime_pair_seqs j
    echo (_8{.":N),' | ',3":{:seqs
  end.
}}

   task 20
       1 |   1  2
       1 |   1  2  3
       1 |   1  2  3  4
       1 |   1  4  3  2  5
       1 |   1  4  3  2  5  6
       2 |   1  6  5  2  3  4  7
       4 |   1  6  7  4  3  2  5  8
       7 |   1  6  7  4  3  8  5  2  9
      24 |   1  6  7  4  9  8  5  2  3 10
      80 |   1 10  9  8  5  6  7  4  3  2 11
     216 |   1 10  9  8 11  6  7  4  3  2  5 12
     648 |   1 12 11  8  9 10  7  6  5  2  3  4 13
    1304 |   1 12 11  8  9 10 13  6  7  4  3  2  5 14
    3392 |   1 12 11  8  9 14  5  6 13 10  7  4  3  2 15
   13808 |   1 12 11  8 15 14  9 10 13  6  5  2  3  4  7 16
   59448 |   1 16 15 14  9 10 13  6 11 12  7  4  3  8  5  2 17
  155464 |   1 16 15 14 17 12 11  8  9 10 13  6  7  4  3  2  5 18
  480728 |   1 18 13 16 15 14 17 12 11  8  9 10  7  6  5  2  3  4 19
 1588162 |   1 18 19 12 17 14 15 16 13 10  9  8 11  2  5  6  7  4  3 20

Java

public class PrimeTriangle {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for (int i = 2; i <= 20; ++i) {
            int[] a = new int[i];
            for (int j = 0; j < i; ++j)
                a[j] = j + 1;
            if (findRow(a, 0, i))
                printRow(a);                
        }
        System.out.println();
        StringBuilder s = new StringBuilder();
        for (int i = 2; i <= 20; ++i) {
            int[] a = new int[i];
            for (int j = 0; j < i; ++j)
                a[j] = j + 1;
            if (i > 2)
                s.append(" ");
            s.append(countRows(a, 0, i));
        }
        System.out.println(s);
        long finish = System.currentTimeMillis();
        System.out.printf("\nElapsed time: %d milliseconds\n", finish - start);
    }

    private static void printRow(int[] a) {
        for (int i = 0; i < a.length; ++i) {
            if (i != 0)
                System.out.print(" ");
            System.out.printf("%2d", a[i]);
        }
        System.out.println();
    }

    private static boolean findRow(int[] a, int start, int length) {
        if (length == 2)
            return isPrime(a[start] + a[start + 1]);
        for (int i = 1; i + 1 < length; i += 2) {
            if (isPrime(a[start] + a[start + i])) {
                swap(a, start + i, start + 1);
                if (findRow(a, start + 1, length - 1))
                    return true;
                swap(a, start + i, start + 1);
            }
        }
        return false;
    }

    private static int countRows(int[] a, int start, int length) {
        int count = 0;
        if (length == 2) {
            if (isPrime(a[start] + a[start + 1]))
                ++count;
        } else {
            for (int i = 1; i + 1 < length; i += 2) {
                if (isPrime(a[start] + a[start + i])) {
                    swap(a, start + i, start + 1);
                    count += countRows(a, start + 1, length - 1);
                    swap(a, start + i, start + 1);
                }
            }
        }
        return count;
    }

    private static void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }

    private static boolean isPrime(int n) {
        return ((1L << n) & 0x28208a20a08a28acL) != 0;
    }
}
Output:
 1  2
 1  2  3
 1  2  3  4
 1  4  3  2  5
 1  4  3  2  5  6
 1  4  3  2  5  6  7
 1  2  3  4  7  6  5  8
 1  2  3  4  7  6  5  8  9
 1  2  3  4  7  6  5  8  9 10
 1  2  3  4  7 10  9  8  5  6 11
 1  2  3  4  7 10  9  8  5  6 11 12
 1  2  3  4  7  6  5 12 11  8  9 10 13
 1  2  3  4  7  6 13 10  9  8 11 12  5 14
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
 1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
 1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Elapsed time: 833 milliseconds

jq

Works with: jq

Adapted from Wren

(gojq requires too much memory to complete the task.)

# $i and $j should be relevant integers (possibly negataive)
# Usage with an array-valued key: .key |= array_swap($i; $j)
def array_swap($i; $j):
  if $i == $j then .
  else .[$i] as $t
  | .[$i] = .[$j]
  | .[$j] = $t
  end;

# For syntactic convenience
def swap($array; $i; $j):
  $array | array_swap($i; $j);

def pmap:
  reduce (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37) as $i ([];
    .[$i] = true)  ;

# input: {bFirst, arrang, canFollow, emit}
# output: same + {res, emit, i, count}
def ptrs($res; $n; $done):
  . + {$res, count: $done}
  | .arrang[$done-1] as $ad
  | if ($n - $done <= 1)
    then if .canFollow[$ad-1][$n-1]
         then if .bFirst
              then .emit += [.arrang]
              | .bFirst = false
              else .
              end
         | .res += 1
         else .
         end
    else .count += 1
    | .count as $count
    | reduce range($count - 1; $n - 1; 2) as $i (.;
        .arrang[$i] as $ai
        | if .canFollow[$ad-1][$ai-1]
          then .arrang = swap(.arrang; $i; $count-1)
          | ptrs(.res; $n; $count)
          | .arrang = swap(.arrang; $i; $count-1)
          else .
          end )
     end;

# Emit {emit, res} from the call to ptrs
def primeTriangle($n):
  pmap as $pmap
  | {}
  | .canFollow = (reduce range(0;$n) as $i ([];
        .[$i] = [range(0;$n) | false]
        | reduce range(0;$n) as $j (.;
            .[$i][$j] = $pmap[$i+$j+2] )))
  | .bFirst = true
  | .arrang = [range(1; 1+$n)]
  | ptrs(0; $n; 1)
  | {emit, res} ;

def task($n):
  range(2;$n+1) as $i
  |  primeTriangle($i) ;

def task($n):
  foreach (range(2;$n+1), null) as $i ({counts: [], emit: null};
    if $i == null then .emit = "\n\(.counts)"
    else primeTriangle($i) as $pt
    | .counts += [$pt|.res]
    | .emit = $pt.emit
    end;
    .emit);

task(20)[]
Output:
[1,2]
[1,2,3]
[1,2,3,4]
[1,4,3,2,5]
[1,4,3,2,5,6]
[1,4,3,2,5,6,7]
[1,2,3,4,7,6,5,8]
[1,2,3,4,7,6,5,8,9]
[1,2,3,4,7,6,5,8,9,10]
[1,2,3,4,7,10,9,8,5,6,11]
[1,2,3,4,7,10,9,8,5,6,11,12]
[1,2,3,4,7,6,5,12,11,8,9,10,13]
[1,2,3,4,7,6,13,10,9,8,11,12,5,14]
[1,2,3,4,7,6,13,10,9,8,11,12,5,14,15]
[1,2,3,4,7,6,5,12,11,8,15,14,9,10,13,16]
[1,2,3,4,7,6,5,12,11,8,9,10,13,16,15,14,17]
[1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,11,18]
[[1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,11,18,19]]
[[1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,19,18,11,20]]

[1,1,1,1,1,2,4,7,24,80,216,648,1304,3392,13808,59448,155464,480728,1588162]

Julia

Filter method

using Combinatorics, Primes

function primetriangle(nrows::Integer)
    nrows < 2 && error("number of rows requested must be > 1")
    pmask, spinlock = primesmask(2 * (nrows + 1)), Threads.SpinLock()
    counts, rowstrings = [1; zeros(Int, nrows - 1)], ["" for _ in 1:nrows]
    for r in 2:nrows
        @Threads.threads for e in collect(permutations(2:2:r))
            p = zeros(Int, r - 1)
            for o in permutations(3:2:r)
                i = 0
                for (x, y) in zip(e, o)
                    p[i += 1] = x
                    p[i += 1] = y
                end
                length(e) > length(o) && (p[i += 1] = e[end])
                if pmask[p[i] + r + 1] && pmask[p[begin] + 1] && all(j -> pmask[p[j] + p[j + 1]], 1:r-2)
                    lock(spinlock)
                    if counts[r] == 0
                        rowstrings[r] = "  1" * prod([lpad(n, 3) for n in p]) * lpad(r + 1, 3) * "\n"
                    end
                    counts[r] += 1
                    unlock(spinlock)
                end
            end
        end
    end
    println("  1  2\n" * prod(rowstrings), "\n", counts)
end

@time primetriangle(16)
Output:
  1  2  
  1  2  3
  1  2  3  4
  1  4  3  2  5
  1  4  3  2  5  6
  1  4  3  2  5  6  7
  1  2  3  4  7  6  5  8
  1  2  3  4  7  6  5  8  9
  1  2  3  4  7  6  5  8  9 10
  1  2  3  4  9 10  7  6  5  8 11
  1  2  3  4  9 10  7  6  5  8 11 12
  1  2  3  4  7  6  5 12 11  8  9 10 13
  1  2  3  4 13  6 11  8  9 10  7 12  5 14
  1  2  3  4 13  6 11  8  9 10  7 12  5 14 15
  1  2  3  4 13  6 11  8  9 10  7 12  5 14 15 16
  1  2 15  4 13  6 11  8  9 10  3 16  7 12  5 14 17

[1, 1, 1, 1, 1, 2, 4, 7, 24, 80, 216, 648, 1304, 3392, 13808, 59448]
  36.933227 seconds (699.10 M allocations: 55.557 GiB, 46.71% gc time, 0.37% compilation time)

Generator method

Similar to the Phix entry.

using Primes

function solverow(row, pos, avail)
    results, nresults = Int[], 0
    for (i, tf) in enumerate(avail)
        if tf && isprime(row[pos - 1] + i + 1)
            if pos >= length(row) - 1 && isprime(row[end] + i + 1)
                row[pos] = i + 1
                return (copy(row), 1)
            else
                row[pos] = i + 1
                newav = copy(avail)
                newav[i] = false
                newresults, n = solverow(copy(row), pos + 1, newav)
                nresults += n
                results = isempty(results) && !isempty(newresults) ? newresults : results
            end
        end
    end
    return results, nresults
end

function primetriangle(nrows::Integer)
    nrows < 2 && error("number of rows requested must be > 1")
    counts, rowstrings = [1; zeros(Int, nrows - 1)], ["" for _ in 1:nrows]
    for r in 2:nrows
        p, n = solverow(collect(1:r+1), 2, trues(r - 1))
        rowstrings[r] = prod([lpad(n, 3) for n in p]) * "\n"
        counts[r] = n
    end
    println("  1  2\n" * prod(rowstrings), "\n", counts)
end
Output:
  1  2  
  1  2  3
  1  2  3  4
  1  4  3  2  5
  1  4  3  2  5  6
  1  4  3  2  5  6  7
  1  2  3  4  7  6  5  8
  1  2  3  4  7  6  5  8  9
  1  2  3  4  7  6  5  8  9 10
  1  2  3  4  7 10  9  8  5  6 11
  1  2  3  4  7 10  9  8  5  6 11 12
  1  2  3  4  7  6  5 12 11  8  9 10 13
  1  2  3  4  7  6 13 10  9  8 11 12  5 14
  1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
  1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
  1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

[1, 1, 1, 1, 1, 2, 4, 7, 24, 80, 216, 648, 1304, 3392, 13808, 59448, 155464, 480728, 1588162]
 25.818809 seconds (249.58 M allocations: 22.295 GiB, 15.56% gc time)

Mathematica/Wolfram Language

ClearAll[FindPrimeTriangles, FindPrimeTrianglesHelper]
FindPrimeTriangles[max_] := 
 Module[{count = 0, firstsolution, primes, primeQ},
  primes = PrimeQ[Range[2 max]];
  primeQ[n_] := primes[[n]];
  ClearAll[FindPrimeTrianglesHelper];
  FindPrimeTrianglesHelper[start_, remainder_, mxx_] := 
   Module[{last, nexts, r, newstart, newremainder},
    If[Length[remainder] > 0,
     last = Last[start];
     Do[
      r = remainder[[ri]];
      If[primeQ[last + r],
       newstart = Append[start, r];
       newremainder = Delete[remainder, ri];
       FindPrimeTrianglesHelper[newstart, newremainder, mxx]
       ]
      ,
      {ri, Length[remainder]}
      ]
     ,
     If[primeQ[Last[start] + mxx],
      count++;
      If[count == 1,
       Print[Append[start, mxx]]
       ]
      ]
     ]
    ];
  FindPrimeTrianglesHelper[{1}, Range[2, max - 1], max];
  count
  ]
Table[FindPrimeTriangles[S],{S, 2, 20}]
Output:
{1,2}
{1,2,3}
{1,2,3,4}
{1,4,3,2,5}
{1,4,3,2,5,6}
{1,4,3,2,5,6,7}
{1,2,3,4,7,6,5,8}
{1,2,3,4,7,6,5,8,9}
{1,2,3,4,7,6,5,8,9,10}
{1,2,3,4,7,10,9,8,5,6,11}
{1,2,3,4,7,10,9,8,5,6,11,12}
{1,2,3,4,7,6,5,12,11,8,9,10,13}
{1,2,3,4,7,6,13,10,9,8,11,12,5,14}
{1,2,3,4,7,6,13,10,9,8,11,12,5,14,15}
{1,2,3,4,7,6,5,12,11,8,15,14,9,10,13,16}
{1,2,3,4,7,6,5,12,11,8,9,10,13,16,15,14,17}
{1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,11,18}
{1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,11,18,19}
{1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,12,19,18,11,20}

{1, 1, 1, 1, 1, 2, 4, 7, 24, 80, 216, 648, 1304, 3392, 13808, 59448, 155464, 480728, 1588162}

Nim

Translation of: C
import std/[monotimes, strutils, times]

const IsPrime = [false, false, true, true, false, true, false, true,
                 false, false, false, true, false, true, false, false,
                 false, true, false, true, false, false, false, true,
                 false, false, false, false, false, true, false, true,
                 false, false, false, false, false, true, false, false,
                 false, true, false, true, false, false, false, true,
                 false, false, false, false, false, true, false, false,
                 false, false, false, true, false, true, false, false]

type TriangleRow = openArray[Natural]

template isPrime(n: Natural): bool = IsPrime[n]

func primeTriangleRow(a: var TriangleRow): bool =
  if a.len == 2:
    return isPrime(a[0] + a[1])
  for i in countup(1, a.len - 2, 2):
    if isPrime(a[0] + a[i]):
      swap a[i], a[1]
      if primeTriangleRow(a.toOpenArray(1, a.high)):
        return true
      swap a[i], a[1]

func primeTriangleCount(a: var TriangleRow): Natural =
  if a.len == 2:
    if isPrime(a[0] + a[1]):
      inc result
  else:
    for i in countup(1, a.len - 2, 2):
      if isPrime(a[0] + a[i]):
        swap a[i], a[1]
        inc result, primeTriangleCount(a.toOpenArray(1, a.high))
        swap a[i], a[1]

proc print(a: TriangleRow) =
  if a.len == 0: return
  for i, n in a:
    if n > 0: stdout.write ' '
    stdout.write align($n, 2)
  stdout.write '\n'

let start = getMonoTime()
for n in 2..20:
  var a = newSeq[Natural](n)
  for i in 0..<n:
    a[i] = i + 1
  if a.primeTriangleRow:
    print a
echo()
for n in 2..20:
  var a = newSeq[Natural](n)
  for i in 0..<n:
    a[i] = i + 1
  if n > 2: stdout.write " "
  stdout.write a.primeTriangleCount
echo '\n'

echo "Elapsed time: ", (getMonoTime() - start).inMilliseconds, " ms"
Output:
  1  2
  1  2  3
  1  2  3  4
  1  4  3  2  5
  1  4  3  2  5  6
  1  4  3  2  5  6  7
  1  2  3  4  7  6  5  8
  1  2  3  4  7  6  5  8  9
  1  2  3  4  7  6  5  8  9 10
  1  2  3  4  7 10  9  8  5  6 11
  1  2  3  4  7 10  9  8  5  6 11 12
  1  2  3  4  7  6  5 12 11  8  9 10 13
  1  2  3  4  7  6 13 10  9  8 11 12  5 14
  1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
  1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
  1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Elapsed time: 535 ms

Pascal

Free Pascal

Simple backtracking.Precaltulated like Prime_triangle#Phix Can_Follow by checking for sum gets prime.

program PrimePyramid;
{$IFDEF FPC}
  {$MODE delphi}{$Optimization ON,ALL}{$CodeAlign proc=32}
{$IFEND}
const
  MAX = 21;//max 8 different  SumToPrime : array[0..MAX,0..7] of byte;
  //MAX = 57;//max 16 different SumToPrime : array[0..MAX,0..15] of byte;
  cMaxAlign32 = (((MAX-1)DIV 32)+1)*32-1;//MAX > 0
type
  tPrimeRange = set of 0..127;
var
  SetOfPrimes :tPrimeRange =[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,
                             53,59,61,67,71,73,79,83,89,97,101,103,107,
                             109,113,127];

  SumToPrime : array[0..cMaxAlign32,0..7] of byte;
//  SumToPrime : array[0..MAX,0..15] of byte;
  SumToPrimeMaxIdx,
  SumMaxIdx,
  Solution,
  FirstSolution    : array[0..cMaxAlign32] of byte;

  free : array[0..cMaxAlign32] of boolean;

  maxused : integer;
  digitcount,SolCount : integer;

procedure InitSumToPrime;
var
  i,j,idx : integer;
begin
  For i := 1 to MAX do
  Begin
    idx := 0;
    For j := 1 to MAX do
      If (i+j) in SetOfPrimes then
      Begin
        SumToPrime[i,idx] := j;
        inc(idx);
      end;
    SumToPrimeMaxIdx[i] := idx;
  end;
end;

procedure InitFree(maxused : integer);
var
  i,j : Integer;
begin
  For i := 0 to 1 do
    Free[i] := false;
  For i := 2 to maxused-1 do
    Free[i] := true;
  For i := maxused to MAX do
    Free[i] := false;
  // search maxidx of max neighour sum to prime
  For i := 1 to maxused-1 do
  begin
    j := SumToPrimeMaxIdx[i]-1;
    while SumToPrime[i,j] > maxused-1 do
      j -= 1;
    SumMaxIdx[i] := j+1;
  end;
end;

procedure CountSolution(digit:integer);
begin
  // check if maxused can follow
  if (digit+maxused) in SetOfPrimes then
  Begin
    if solcount = 0 then
       FirstSolution := Solution;
    inc(solCount);
  end;
end;

procedure checkDigits(digit:integer);
var
  idx,nextDigit: integer;
begin
  idx := 0;
  repeat
    nextDigit := SumToPrime[digit,idx];
    if Free[nextdigit] then
    Begin
      Solution[digitcount] := nextDigit;
      dec(digitcount);
      IF digitcount = 0 then
        CountSolution(nextDigit);
      free[nextdigit]:= false;
      checkDigits(nextdigit);
      inc(digitcount);
      free[nextdigit]:= true;
    end;
    inc(idx);
  until idx >= SumMaxIdx[digit];
end;

var
  i,j : integer;
Begin
  InitSumToPrime;
  writeln('number|   count|  first solution');
  writeln('   2|         1|  1  2');
  For i := 3 to 20 do
  Begin
    maxused := i;
    InitFree(i);
    digitcount := i-2;
    solCount := 0;
    checkDigits(1);
    write(i:4,'|',solcount:10,'|  1');
    For j := i-2 downto 1 do
      write( FirstSolution[j]:3);
    writeln(i:3);
  end;
end.
@TIO.RUN:
number|   count|  first solution
   2|         1|  1  2
   3|         1|  1  2  3
   4|         1|  1  2  3  4
   5|         1|  1  4  3  2  5
   6|         1|  1  4  3  2  5  6
   7|         2|  1  4  3  2  5  6  7
   8|         4|  1  2  3  4  7  6  5  8
   9|         7|  1  2  3  4  7  6  5  8  9
  10|        24|  1  2  3  4  7  6  5  8  9 10
  11|        80|  1  2  3  4  7 10  9  8  5  6 11
  12|       216|  1  2  3  4  7 10  9  8  5  6 11 12
  13|       648|  1  2  3  4  7  6  5 12 11  8  9 10 13
  14|      1304|  1  2  3  4  7  6 13 10  9  8 11 12  5 14
  15|      3392|  1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
  16|     13808|  1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
  17|     59448|  1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
  18|    155464|  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
  19|    480728|  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
  20|   1588162|  1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20
Real time: 1.827 s User time: 1.794 s Sys. time: 0.021 s CPU share: 99.36 %
@home: real 0m0,679s

Perl

Translation of: Raku
Library: ntheory
use strict;
use warnings;
use feature 'say';
use ntheory 'is_prime';
use List::MoreUtils qw(zip slideatatime);
use Algorithm::Combinatorics qw(permutations);

say '1 2';

my @count = (0, 0, 1);

for my $n (3..17) {
    my @even_nums = grep { 0 == $_ % 2 } 2..$n-1;
    my @odd_nums  = grep { 1 == $_ % 2 } 3..$n-1;
    for my $e (permutations [@even_nums]) {
        next if $$e[0] == 8 or $$e[0] == 14;
        my $nope = 0;
        for my $o (permutations [@odd_nums]) {
            my @list = (zip(@$e, @$o), $n);                 # 'zip' makes a list with a gap if more evens than odds
            splice @list, -2, -1 if not defined $list[-2];  # in which case splice out 'undef' in next-to-last position
            my $it = slideatatime(1, 2, @list);
            while ( my @rr = $it->() ) {
                last unless defined $rr[1];
                $nope++ and last unless is_prime $rr[0]+$rr[1];
            }
            unless ($nope) {
                say '1 ' . join ' ', @list unless $count[$n];
                $count[$n]++;
            }
            $nope = 0;
        }
    }
}

say "\n" . join ' ', @count[2..$#count];
Output:
1 2
1 2 3
1 2 3 4
1 4 3 2 5
1 4 3 2 5 6
1 4 3 2 5 6 7
1 2 3 4 7 6 5 8
1 2 3 4 7 6 5 8 9
1 2 3 4 7 6 5 8 9 10
1 2 3 4 9 10 7 6 5 8 11
1 2 3 4 9 10 7 6 5 8 11 12
1 2 3 4 7 6 5 12 11 8 9 10 13
1 2 3 4 13 6 11 8 9 10 7 12 5 14
1 2 3 4 13 6 11 8 9 10 7 12 5 14 15
1 2 3 4 13 6 11 8 9 10 7 12 5 14 15 16
1 2 15 4 13 6 11 8 9 10 3 16 7 12 5 14 17

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448

Phix

Library: Phix/online

Not sure this counts as particularly clever but by the sound of things it's quite a bit faster than the other entries so far. 😎
You can run this online here (expect a blank screen for about 24s).

with javascript_semantics
atom t0 = time()
sequence can_follow, arrang
bool bFirst = true

function ptrs(integer res, n, done)
    -- prime triangle recursive sub-procedure
    -- on entry, arrang[done] is set and arrang[$]==n.
    -- find something/everything that fits between them.
    integer ad = arrang[done]
    if n-done<=1 then
        if can_follow[ad][n] then
            if bFirst then
                printf(1,"%s\n",join(arrang,fmt:="%d"))
                bFirst = false
            end if
            res += 1
        end if
    else
        done += 1
        -- as per talk page, we only need to examine odd
        -- numbers following an even number & vice versa
        for i=done to n-1 by 2 do
            integer ai = arrang[i]
            if can_follow[ad][ai] then
                integer aid = arrang[done]
                arrang[i] = aid
                arrang[done] = ai
                res = ptrs(res,n,done)
                arrang[i] = ai
                arrang[done] = aid
            end if
        end for
    end if
    return res
end function

function prime_triangle(integer n)
    can_follow = repeat(repeat(false,n),n)
    for i=1 to n do
        for j=1 to n do
            can_follow[i][j] = is_prime(i+j)
        end for
    end for
    arrang = tagset(n)
    bFirst = true
    return ptrs(0,n,1)
end function

sequence res = apply(tagset(20,2),prime_triangle)
printf(1,"%s\n",join(res,fmt:="%d"))
?elapsed(time()-t0)
Output:
1 2
1 2 3
1 2 3 4
1 4 3 2 5
1 4 3 2 5 6
1 4 3 2 5 6 7
1 2 3 4 7 6 5 8
1 2 3 4 7 6 5 8 9
1 2 3 4 7 6 5 8 9 10
1 2 3 4 7 10 9 8 5 6 11
1 2 3 4 7 10 9 8 5 6 11 12
1 2 3 4 7 6 5 12 11 8 9 10 13
1 2 3 4 7 6 13 10 9 8 11 12 5 14
1 2 3 4 7 6 13 10 9 8 11 12 5 14 15
1 2 3 4 7 6 5 12 11 8 15 14 9 10 13 16
1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14 17
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20
1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162
"9.7s"

Python

from numpy import array
# for Rosetta Code by MG - 20230312
def is_prime(n: int) -> bool:
    assert n < 64
    return ((1 << n) & 0x28208a20a08a28ac) != 0

def prime_triangle_row(a: array, start: int, length: int) -> bool:
    if length == 2:
        return is_prime(a[0] + a[1])
    for i in range(1, length - 1, 1):
        if is_prime(a[start] + a[start + i]):
            a[start + i], a[start + 1] = a[start + 1], a[start + i]
            if prime_triangle_row(a, start + 1, length - 1):
                return True
            a[start + i], a[start + 1] = a[start + 1], a[start + i]
    return False

def prime_triangle_count(a: array, start: int, length: int) -> int:
    count: int = 0
    if length == 2:
        if is_prime(a[start] + a[start + 1]):
            count += 1
    else:
        for i in range(1, length - 1, 1):
            if is_prime(a[start] + a[start + i]):
                a[start + i], a[start + 1] = a[start + 1], a[start + i]
                count += prime_triangle_count(a, start + 1, length - 1)
                a[start + i], a[start + 1] = a[start + 1], a[start + i]
    return count

def print_row(a: array):
    if a == []:
        return
    print("%2d"% a[0], end=" ")
    for x in a[1:]:
        print("%2d"% x, end=" ")
    print()

for n in range(2, 21):
    tr: array = [_ for _ in range(1, n + 1)]
    if prime_triangle_row(tr, 0, n):
        print_row(tr)
print()
for n in range(2, 21):
    tr: array = [_ for _ in range(1, n + 1)]
    if n > 2:
        print(" ", end="")
    print(prime_triangle_count(tr, 0, n), end="")
print()
Output:
 1  2 
 1  2  3 
 1  2  3  4 
 1  2  3  4  5 
 1  4  3  2  5  6 
 1  4  3  2  5  6  7 
 1  2  3  4  7  6  5  8 
 1  2  3  4  7  6  5  8  9 
 1  2  3  4  7  6  5  8  9 10 
 1  2  3  4  7  6  5  8  9 10 11 
 1  2  3  4  7 10  9  8  5  6 11 12 
 1  2  3  4  7  6  5 12 11  8  9 10 13 
 1  2  3  4  7  6  5 12 11  8  9 10 13 14 
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 15 
 1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16 
 1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17 
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19 
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19 20 

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Raku

Limit the upper threshold a bit to avoid multiple hours of pointless calculations. Even just up to 17 takes over 20 minutes.

my @count = 0, 0, 1;
my $lock = Lock.new;
put (1,2);

for 3..17 -> $n {
    my @even = (2..^$n).grep: * %% 2;
    my @odd  = (3..^$n).grep: so * % 2;
    @even.permutations.race.map: -> @e {
        quietly next if @e[0] == 8|14;
        my $nope = 0;
        for @odd.permutations -> @o {
            quietly next unless (@e[0] + @o[0]).is-prime;
            my @list;
            for (@list = (flat (roundrobin(@e, @o)), $n)).rotor(2 => -1) {
                $nope++ and last unless .sum.is-prime;
            }
            unless $nope {
                put '1 ', @list unless @count[$n];
                $lock.protect({ @count[$n]++ });
            }
            $nope = 0;
        }
    }
}
put "\n", @count[2..*];
Output:
1 2
1 2 3
1 2 3 4
1 4 3 2 5
1 4 3 2 5 6
1 4 3 2 5 6 7
1 2 3 4 7 6 5 8
1 2 3 4 7 6 5 8 9
1 2 3 4 7 6 5 8 9 10
1 6 5 8 3 10 7 4 9 2 11
1 6 5 8 3 10 7 4 9 2 11 12
1 4 3 2 5 8 9 10 7 12 11 6 13
1 4 3 2 11 8 9 10 13 6 7 12 5 14
1 2 3 8 5 12 11 6 7 10 13 4 9 14 15
1 2 3 8 5 12 11 6 7 10 13 4 9 14 15 16
1 2 9 4 7 10 13 6 5 14 3 16 15 8 11 12 17

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448

Rust

fn is_prime(n: u32) -> bool {
    assert!(n < 64);
    ((1u64 << n) & 0x28208a20a08a28ac) != 0
}

fn prime_triangle_row(a: &mut [u32]) -> bool {
    if a.len() == 2 {
        return is_prime(a[0] + a[1]);
    }
    for i in (1..a.len() - 1).step_by(2) {
        if is_prime(a[0] + a[i]) {
            a.swap(i, 1);
            if prime_triangle_row(&mut a[1..]) {
                return true;
            }
            a.swap(i, 1);
        }
    }
    false
}

fn prime_triangle_count(a: &mut [u32]) -> u32 {
    let mut count = 0;
    if a.len() == 2 {
        if is_prime(a[0] + a[1]) {
            count += 1;
        }
    } else {
        for i in (1..a.len() - 1).step_by(2) {
            if is_prime(a[0] + a[i]) {
                a.swap(i, 1);
                count += prime_triangle_count(&mut a[1..]);
                a.swap(i, 1);
            }
        }
    }
    count
}

fn print(a: &[u32]) {
    if a.is_empty() {
        return;
    }
    print!("{:2}", a[0]);
    for x in &a[1..] {
        print!(" {:2}", x);
    }
    println!();
}

fn main() {
    use std::time::Instant;
    let start = Instant::now();
    for n in 2..21 {
        let mut a: Vec<u32> = (1..=n).collect();
        if prime_triangle_row(&mut a) {
            print(&a);
        }
    }
    println!();
    for n in 2..21 {
        let mut a: Vec<u32> = (1..=n).collect();
        if n > 2 {
            print!(" ");
        }
        print!("{}", prime_triangle_count(&mut a));
    }
    println!();
    let time = start.elapsed();
    println!("\nElapsed time: {} milliseconds", time.as_millis());
}
Output:
 1  2
 1  2  3
 1  2  3  4
 1  4  3  2  5
 1  4  3  2  5  6
 1  4  3  2  5  6  7
 1  2  3  4  7  6  5  8
 1  2  3  4  7  6  5  8  9
 1  2  3  4  7  6  5  8  9 10
 1  2  3  4  7 10  9  8  5  6 11
 1  2  3  4  7 10  9  8  5  6 11 12
 1  2  3  4  7  6  5 12 11  8  9 10 13
 1  2  3  4  7  6 13 10  9  8 11 12  5 14
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
 1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
 1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Elapsed time: 674 milliseconds

Swift

import Foundation

func isPrime(_ n: Int) -> Bool {
    guard n > 0 && n < 64 else {
        return false
    }
    return ((UInt64(1) << n) & 0x28208a20a08a28ac) != 0
}

func primeTriangleRow(_ a: inout [Int], start: Int, length: Int) -> Bool {
    if length == 2 {
        return isPrime(a[start] + a[start + 1])
    }
    for i in stride(from: 1, to: length - 1, by: 2) {
        let index = start + i
        if isPrime(a[start] + a[index]) {
            a.swapAt(index, start + 1)
            if primeTriangleRow(&a, start: start + 1, length: length - 1) {
                return true
            }
            a.swapAt(index, start + 1)
        }
    }
    return false
}

func primeTriangleCount(_ a: inout [Int], start: Int, length: Int) -> Int {
    var count = 0
    if length == 2 {
        if isPrime(a[start] + a[start + 1]) {
            count += 1
        }
    } else {
        for i in stride(from: 1, to: length - 1, by: 2) {
            let index = start + i
            if isPrime(a[start] + a[index]) {
                a.swapAt(index, start + 1)
                count += primeTriangleCount(&a, start: start + 1, length: length - 1)
                a.swapAt(index, start + 1)
            }
        }
    }
    return count
}

func printRow(_ a: [Int]) {
    if a.count == 0 {
        return
    }
    print(String(format: "%2d", a[0]), terminator: "")
    for x in a[1...] {
        print(String(format: " %2d", x), terminator: "")
    }
    print()
}

let startTime = CFAbsoluteTimeGetCurrent()

for n in 2...20 {
    var a = Array(1...n)
    if primeTriangleRow(&a, start: 0, length: n) {
        printRow(a)
    }
}
print()

for n in 2...20 {
    var a = Array(1...n)
    if n > 2 {
        print(" ", terminator: "")
    }
    print("\(primeTriangleCount(&a, start: 0, length: n))", terminator: "")
}
print()

let endTime = CFAbsoluteTimeGetCurrent()
print("\nElapsed time: \(endTime - startTime) seconds")
Output:
 1  2
 1  2  3
 1  2  3  4
 1  4  3  2  5
 1  4  3  2  5  6
 1  4  3  2  5  6  7
 1  2  3  4  7  6  5  8
 1  2  3  4  7  6  5  8  9
 1  2  3  4  7  6  5  8  9 10
 1  2  3  4  7 10  9  8  5  6 11
 1  2  3  4  7 10  9  8  5  6 11 12
 1  2  3  4  7  6  5 12 11  8  9 10 13
 1  2  3  4  7  6 13 10  9  8 11 12  5 14
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
 1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
 1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162

Elapsed time: 1.0268970727920532 seconds

Wren

Translation of: Phix
Library: Wren-fmt

Takes around 18.7 seconds which is fine for Wren.

import "./fmt" for Fmt

var canFollow = []
var arrang = []
var bFirst = true

var pmap = {}
for (i in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]) {
    pmap[i] = true
}

var ptrs
ptrs = Fn.new { |res, n, done|
    var ad = arrang[done-1]
    if (n - done <= 1) {
        if (canFollow[ad-1][n-1]) {
            if (bFirst) {
                Fmt.print("$2d", arrang)
                bFirst = false
            }
            res = res + 1
        }
    } else {
        done = done + 1
        var i = done - 1
        while (i <= n-2) {
            var ai = arrang[i]
            if (canFollow[ad-1][ai-1]) {
                arrang.swap(i, done-1)
                res = ptrs.call(res, n, done)
                arrang.swap(i, done-1)
            }
            i = i + 2
        }
    }
    return res
}

var primeTriangle = Fn.new { |n|
    canFollow = List.filled(n, null)
    for (i in 0...n) {
        canFollow[i] = List.filled(n, false)
        for (j in 0...n) canFollow[i][j] = pmap.containsKey(i+j+2)
    }
    bFirst = true
    arrang = (1..n).toList
    return ptrs.call(0, n, 1)
}

var counts = []
for (i in 2..20) {
    counts.add(primeTriangle.call(i))
}
System.print()
System.print(counts.join(" "))
Output:
 1  2
 1  2  3
 1  2  3  4
 1  4  3  2  5
 1  4  3  2  5  6
 1  4  3  2  5  6  7
 1  2  3  4  7  6  5  8
 1  2  3  4  7  6  5  8  9
 1  2  3  4  7  6  5  8  9 10
 1  2  3  4  7 10  9  8  5  6 11
 1  2  3  4  7 10  9  8  5  6 11 12
 1  2  3  4  7  6  5 12 11  8  9 10 13
 1  2  3  4  7  6 13 10  9  8 11 12  5 14
 1  2  3  4  7  6 13 10  9  8 11 12  5 14 15
 1  2  3  4  7  6  5 12 11  8 15 14  9 10 13 16
 1  2  3  4  7  6  5 12 11  8  9 10 13 16 15 14 17
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 11 18 19
 1  2  3  4  7  6  5  8  9 10 13 16 15 14 17 12 19 18 11 20

1 1 1 1 1 2 4 7 24 80 216 648 1304 3392 13808 59448 155464 480728 1588162