Consecutive primes with ascending or descending differences
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Find and display here on this page, the longest sequence of consecutive prime numbers where the differences between the primes are strictly ascending.
Do the same for sequences of primes where the differences are strictly descending.
In both cases, show the sequence for primes < 1,000,000.
If there are multiple sequences of the same length, only the first need be shown.
ALGOL 68
<lang algol68>BEGIN # find sequences of primes where the gaps between the elements #
# are strictly ascending/descending # # reurns a list of primes up to n # PROC prime list = ( INT n )[]INT: BEGIN # sieve the primes to n # INT no = 0, yes = 1; [ 1 : n ]INT p; p[ 1 ] := no; p[ 2 ] := yes; FOR i FROM 3 BY 2 TO n DO p[ i ] := yes OD; FOR i FROM 4 BY 2 TO n DO p[ i ] := no OD; FOR i FROM 3 BY 2 TO ENTIER sqrt( n ) DO IF p[ i ] = yes THEN FOR s FROM i * i BY i + i TO n DO p[ s ] := no OD FI OD; # replace the sieve with a list # INT p pos := 0; FOR i TO n DO IF p[ i ] = yes THEN p[ p pos +:= 1 ] := i FI OD; p[ 1 : p pos ] END # prime list # ; # shos the results of a search # PROC show sequence = ( []INT primes, STRING seq name, INT seq start, seq length )VOID: BEGIN print( ( " The longest sequence of primes with " , seq name , " differences contains " , whole( seq length, 0 ) , " primes" , newline , " First such sequence (differences in brackets):" , newline , " " ) ); print( ( whole( primes[ seq start ], 0 ) ) ); FOR p FROM seq start + 1 TO seq start + ( seq length - 1 ) DO print( ( " (", whole( ABS( primes[ p ] - primes[ p - 1 ] ), 0 ), ") ", whole( primes[ p ], 0 ) ) ) OD; print( ( newline ) ) END # show seuence # ; # find the longest sequence of primes where the successive differences are ascending/descending # PROC find sequence = ( []INT primes, BOOL ascending, REF INT seq start, seq length )VOID: BEGIN seq start := seq length := 0; INT start diff = IF ascending THEN 0 ELSE UPB primes + 1 FI; FOR p FROM LWB primes TO UPB primes DO INT prev diff := start diff; INT length := 1; FOR s FROM p + 1 TO UPB primes WHILE INT diff = ABS ( primes[ s ] - primes[ s - 1 ] ); IF ascending THEN diff > prev diff ELSE diff < prev diff FI DO length +:= 1; prev diff := diff OD; IF length > seq length THEN # found a longer sequence # seq length := length; seq start := p FI OD END # find sequence #; INT max number = 1 000 000; []INT primes = prime list( max number ); INT asc length := 0; INT asc start := 0; INT desc length := 0; INT desc start := 0; find sequence( primes, TRUE, asc start, asc length ); find sequence( primes, FALSE, desc start, desc length ); # show the sequences # print( ( "For primes up to ", whole( max number, 0 ), newline ) ); show sequence( primes, "ascending", asc start, asc length ); show sequence( primes, "descending", desc start, desc length )
END</lang>
- Output:
For primes up to 1000000 The longest sequence of primes with ascending differences contains 8 primes First such sequence (differences in brackets): 128981 (2) 128983 (4) 128987 (6) 128993 (8) 129001 (10) 129011 (12) 129023 (14) 129037 The longest sequence of primes with descending differences contains 8 primes First such sequence (differences in brackets): 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249
C#
Extended the limit up to see what would happen. <lang csharp>using System.Linq; using System.Collections.Generic; using TG = System.Tuple<int, int>; using static System.Console;
class Program {
static void Main(string[] args) { const int mil = (int)1e6; foreach (var amt in new int[] { 1, 2, 6, 12, 18 }) { int lmt = mil * amt, lg = 0, ng, d, ld = 0; var desc = new string[] { "A", "", "De" }; int[] mx = new int[] { 0, 0, 0 }, bi = new int[] { 0, 0, 0 }, c = new int[] { 2, 2, 2 }; WriteLine("For primes up to {0:n0}:", lmt); var pr = PG.Primes(lmt).ToArray(); for (int i = 0; i < pr.Length; i++) { ng = pr[i].Item2; d = ng.CompareTo(lg) + 1; if (ld == d) c[2 - d]++; else { if (c[d] > mx[d]) { mx[d] = c[d]; bi[d] = i - mx[d] - 1; } c[d] = 2; } ld = d; lg = ng; } for (int r = 0; r <= 2; r += 2) { Write("{0}scending, found run of {1} consecutive primes:\n {2} ", desc[r], mx[r] + 1, pr[bi[r]++].Item1); foreach (var itm in pr.Skip(bi[r]).Take(mx[r])) Write("({0}) {1} ", itm.Item2, itm.Item1); WriteLine(r == 0 ? "" : "\n"); } } }
}
class PG {
public static IEnumerable<TG> Primes(int lim) { bool[] flags = new bool[lim + 1]; int j = 3, lj = 2; for (int d = 8, sq = 9; sq <= lim; j += 2, sq += d += 8) if (!flags[j]) { yield return new TG(j, j - lj); lj = j; for (int k = sq, i = j << 1; k <= lim; k += i) flags[k] = true; } for (; j <= lim; j += 2) if (!flags[j]) { yield return new TG(j, j - lj); lj = j; } }
}</lang>
- Output:
For primes up to 1,000,000: Ascending, found run of 8 consecutive primes: 128981 (2) 128983 (4) 128987 (6) 128993 (8) 129001 (10) 129011 (12) 129023 (14) 129037 Descending, found run of 8 consecutive primes: 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249 For primes up to 2,000,000: Ascending, found run of 9 consecutive primes: 1319407 (4) 1319411 (8) 1319419 (10) 1319429 (14) 1319443 (16) 1319459 (18) 1319477 (32) 1319509 (34) 1319543 Descending, found run of 8 consecutive primes: 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249 For primes up to 6,000,000: Ascending, found run of 9 consecutive primes: 1319407 (4) 1319411 (8) 1319419 (10) 1319429 (14) 1319443 (16) 1319459 (18) 1319477 (32) 1319509 (34) 1319543 Descending, found run of 9 consecutive primes: 5051309 (32) 5051341 (28) 5051369 (14) 5051383 (10) 5051393 (8) 5051401 (6) 5051407 (4) 5051411 (2) 5051413 For primes up to 12,000,000: Ascending, found run of 9 consecutive primes: 1319407 (4) 1319411 (8) 1319419 (10) 1319429 (14) 1319443 (16) 1319459 (18) 1319477 (32) 1319509 (34) 1319543 Descending, found run of 10 consecutive primes: 11938793 (60) 11938853 (38) 11938891 (28) 11938919 (14) 11938933 (10) 11938943 (8) 11938951 (6) 11938957 (4) 11938961 (2) 11938963 For primes up to 18,000,000: Ascending, found run of 10 consecutive primes: 17797517 (2) 17797519 (4) 17797523 (8) 17797531 (10) 17797541 (12) 17797553 (20) 17797573 (28) 17797601 (42) 17797643 (50) 17797693 Descending, found run of 10 consecutive primes: 11938793 (60) 11938853 (38) 11938891 (28) 11938919 (14) 11938933 (10) 11938943 (8) 11938951 (6) 11938957 (4) 11938961 (2) 11938963
C++
<lang cpp>#include <cstdint>
- include <iostream>
- include <vector>
- include <primesieve.hpp>
void print_diffs(const std::vector<uint64_t>& vec) {
for (size_t i = 0, n = vec.size(); i != n; ++i) { if (i != 0) std::cout << " (" << vec[i] - vec[i - 1] << ") "; std::cout << vec[i]; } std::cout << '\n';
}
int main() {
std::cout.imbue(std::locale("")); std::vector<uint64_t> asc, desc; std::vector<std::vector<uint64_t>> max_asc, max_desc; size_t max_asc_len = 0, max_desc_len = 0; uint64_t prime; const uint64_t limit = 1000000; for (primesieve::iterator pi; (prime = pi.next_prime()) < limit; ) { size_t alen = asc.size(); if (alen > 1 && prime - asc[alen - 1] <= asc[alen - 1] - asc[alen - 2]) asc.erase(asc.begin(), asc.end() - 1); asc.push_back(prime); if (asc.size() >= max_asc_len) { if (asc.size() > max_asc_len) { max_asc_len = asc.size(); max_asc.clear(); } max_asc.push_back(asc); } size_t dlen = desc.size(); if (dlen > 1 && prime - desc[dlen - 1] >= desc[dlen - 1] - desc[dlen - 2]) desc.erase(desc.begin(), desc.end() - 1); desc.push_back(prime); if (desc.size() >= max_desc_len) { if (desc.size() > max_desc_len) { max_desc_len = desc.size(); max_desc.clear(); } max_desc.push_back(desc); } } std::cout << "Longest run(s) of ascending prime gaps up to " << limit << ":\n"; for (const auto& v : max_asc) print_diffs(v); std::cout << "\nLongest run(s) of descending prime gaps up to " << limit << ":\n"; for (const auto& v : max_desc) print_diffs(v); return 0;
}</lang>
- Output:
Longest run(s) of ascending prime gaps up to 1,000,000: 128,981 (2) 128,983 (4) 128,987 (6) 128,993 (8) 129,001 (10) 129,011 (12) 129,023 (14) 129,037 402,581 (2) 402,583 (4) 402,587 (6) 402,593 (8) 402,601 (12) 402,613 (18) 402,631 (60) 402,691 665,111 (2) 665,113 (4) 665,117 (6) 665,123 (8) 665,131 (10) 665,141 (12) 665,153 (24) 665,177 Longest run(s) of descending prime gaps up to 1,000,000: 322,171 (22) 322,193 (20) 322,213 (16) 322,229 (8) 322,237 (6) 322,243 (4) 322,247 (2) 322,249 752,207 (44) 752,251 (12) 752,263 (10) 752,273 (8) 752,281 (6) 752,287 (4) 752,291 (2) 752,293
This task uses Extensible Prime Generator (F#)
F#
<lang fsharp> // Longest ascending and decending sequences of difference between consecutive primes: Nigel Galloway. April 5th., 2021 let fN g fW=primes32()|>Seq.takeWhile((>)g)|>Seq.pairwise|>Seq.fold(fun(n,i,g)el->let w=fW el in match w>n with true->(w,el::i,g) |_->(w,[el],if List.length i>List.length g then i else g))(0,[],[]) for i in [1;2;6;12;18;100] do let _,_,g=fN(i*1000000)(fun(n,g)->g-n) in printfn "Longest ascending upto %d000000->%d:" i (g.Length+1); g|>List.rev|>List.iter(fun(n,g)->printf "%d (%d) %d " n (g-n) g); printfn ""
let _,_,g=fN(i*1000000)(fun(n,g)->n-g) in printfn "Longest decending upto %d000000->%d:" i (g.Length+1); g|>List.rev|>List.iter(fun(n,g)->printf "%d (%d) %d " n (g-n) g); printfn ""
</lang>
- Output:
Longest ascending upto 1000000->8: 128981 (2) 128983 128983 (4) 128987 128987 (6) 128993 128993 (8) 129001 129001 (10) 129011 129011 (12) 129023 129023 (14) 129037 Longest decending upto 1000000->8: 322171 (22) 322193 322193 (20) 322213 322213 (16) 322229 322229 (8) 322237 322237 (6) 322243 322243 (4) 322247 322247 (2) 322249 Longest ascending upto 2000000->9: 1319407 (4) 1319411 1319411 (8) 1319419 1319419 (10) 1319429 1319429 (14) 1319443 1319443 (16) 1319459 1319459 (18) 1319477 1319477 (32) 1319509 1319509 (34) 1319543 Longest decending upto 2000000->8: 322171 (22) 322193 322193 (20) 322213 322213 (16) 322229 322229 (8) 322237 322237 (6) 322243 322243 (4) 322247 322247 (2) 322249 Longest ascending upto 6000000->9: 1319407 (4) 1319411 1319411 (8) 1319419 1319419 (10) 1319429 1319429 (14) 1319443 1319443 (16) 1319459 1319459 (18) 1319477 1319477 (32) 1319509 1319509 (34) 1319543 Longest decending upto 6000000->9: 5051309 (32) 5051341 5051341 (28) 5051369 5051369 (14) 5051383 5051383 (10) 5051393 5051393 (8) 5051401 5051401 (6) 5051407 5051407 (4) 5051411 5051411 (2) 5051413 Longest ascending upto 12000000->9: 1319407 (4) 1319411 1319411 (8) 1319419 1319419 (10) 1319429 1319429 (14) 1319443 1319443 (16) 1319459 1319459 (18) 1319477 1319477 (32) 1319509 1319509 (34) 1319543 Longest decending upto 12000000->10: 11938793 (60) 11938853 11938853 (38) 11938891 11938891 (28) 11938919 11938919 (14) 11938933 11938933 (10) 11938943 11938943 (8) 11938951 11938951 (6) 11938957 11938957 (4) 11938961 11938961 (2) 11938963 Longest ascending upto 18000000->10: 17797517 (2) 17797519 17797519 (4) 17797523 17797523 (8) 17797531 17797531 (10) 17797541 17797541 (12) 17797553 17797553 (20) 17797573 17797573 (28) 17797601 17797601 (42) 17797643 17797643 (50) 17797693 Longest decending upto 18000000->10: 11938793 (60) 11938853 11938853 (38) 11938891 11938891 (28) 11938919 11938919 (14) 11938933 11938933 (10) 11938943 11938943 (8) 11938951 11938951 (6) 11938957 11938957 (4) 11938961 11938961 (2) 11938963 Longest ascending upto 100000000->11: 94097537 (2) 94097539 94097539 (4) 94097543 94097543 (8) 94097551 94097551 (10) 94097561 94097561 (12) 94097573 94097573 (14) 94097587 94097587 (16) 94097603 94097603 (18) 94097621 94097621 (30) 94097651 94097651 (32) 94097683 Longest decending upto 100000000->10: 11938793 (60) 11938853 11938853 (38) 11938891 11938891 (28) 11938919 11938919 (14) 11938933 11938933 (10) 11938943 11938943 (8) 11938951 11938951 (6) 11938957 11938957 (4) 11938961 11938961 (2) 11938963 Real: 00:00:04.708
Factor
<lang factor>USING: arrays assocs formatting grouping io kernel literals math math.primes math.statistics sequences sequences.extras tools.memory.private ;
<< CONSTANT: limit 1,000,000 >>
CONSTANT: primes $[ limit primes-upto ]
- run ( n quot -- seq quot )
[ primes ] [ <clumps> ] [ ] tri* '[ differences _ monotonic? ] ; inline
- max-run ( quot -- n )
1 swap '[ 1 + dup _ run find drop ] loop 1 - ; inline
- runs ( quot -- seq )
[ max-run ] keep run filter ; inline
- .run ( seq -- )
dup differences [ [ commas ] map ] bi@ [ "(" ")" surround ] map 2array round-robin " " join print ;
- .runs ( quot -- )
[ runs ] keep [ < ] = "rising" "falling" ? limit commas "Largest run(s) of %s gaps between primes less than %s:\n" printf [ .run ] each ; inline
[ < ] [ > ] [ .runs nl ] bi@</lang>
- Output:
Largest run(s) of rising gaps between primes less than 1,000,000: 128,981 (2) 128,983 (4) 128,987 (6) 128,993 (8) 129,001 (10) 129,011 (12) 129,023 (14) 129,037 402,581 (2) 402,583 (4) 402,587 (6) 402,593 (8) 402,601 (12) 402,613 (18) 402,631 (60) 402,691 665,111 (2) 665,113 (4) 665,117 (6) 665,123 (8) 665,131 (10) 665,141 (12) 665,153 (24) 665,177 Largest run(s) of falling gaps between primes less than 1,000,000: 322,171 (22) 322,193 (20) 322,213 (16) 322,229 (8) 322,237 (6) 322,243 (4) 322,247 (2) 322,249 752,207 (44) 752,251 (12) 752,263 (10) 752,273 (8) 752,281 (6) 752,287 (4) 752,291 (2) 752,293
FreeBASIC
Use any of the primality testing code on this site as an include; I won't reproduce it here. <lang freebasic>#define UPPER 1000000
- include"isprime.bas"
dim as uinteger champ = 0, record = 0, streak, i, j, n
'first generate all the primes below UPPER redim as uinteger prime(1 to 2) prime(1) = 2 : prime(2) = 3 for i = 5 to UPPER step 2
if isprime(i) then redim preserve prime(1 to ubound(prime) + 1) prime(ubound(prime)) = i end if
next i n = ubound(prime)
'now look for the longest streak of ascending primes for i = 2 to n-1
j = i + 1 streak = 1 while j<=n andalso prime(j)-prime(j-1) > prime(j-1)-prime(j-2) streak += 1 j+=1 wend if streak > record then champ = i-1 record = streak end if
next i
print "The longest sequence of ascending primes (with their difference from the last one) is:" for i = champ+1 to champ+record
print prime(i-1);" (";prime(i)-prime(i-1);") ";
next i print prime(i-1) : print 'now for the descending ones
record = 0 : champ = 0 for i = 2 to n-1
j = i + 1 streak = 1 while j<=n andalso prime(j)-prime(j-1) < prime(j-1)-prime(j-2) 'identical to above, but for the inequality sign streak += 1 j+=1 wend if streak > record then champ = i-1 record = streak end if
next i
print "The longest sequence of descending primes (with their difference from the last one) is:" for i = champ+1 to champ+record
print prime(i-1);" (";prime(i)-prime(i-1);") ";
next i print prime(i-1)</lang>
- Output:
The longest sequence of ascending primes (with their difference from the last one) is: 128981 (2) 128983 (4) 128987 (6) 128993 (8) 129001 (10) 129011 (12) 129023 (14) 129037 The longest sequence of descending primes (with their difference from the last one) is: 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249
Go
<lang go>package main
import (
"fmt" "rcu"
)
const LIMIT = 999999
var primes = rcu.Primes(LIMIT)
func longestSeq(dir string) {
pd := 0 longSeqs := [][]intTemplate:2 currSeq := []int{2} for i := 1; i < len(primes); i++ { d := primes[i] - primes[i-1] if (dir == "ascending" && d <= pd) || (dir == "descending" && d >= pd) { if len(currSeq) > len(longSeqs[0]) { longSeqs = [][]int{currSeq} } else if len(currSeq) == len(longSeqs[0]) { longSeqs = append(longSeqs, currSeq) } currSeq = []int{primes[i-1], primes[i]} } else { currSeq = append(currSeq, primes[i]) } pd = d } if len(currSeq) > len(longSeqs[0]) { longSeqs = [][]int{currSeq} } else if len(currSeq) == len(longSeqs[0]) { longSeqs = append(longSeqs, currSeq) } fmt.Println("Longest run(s) of primes with", dir, "differences is", len(longSeqs[0]), ":") for _, ls := range longSeqs { var diffs []int for i := 1; i < len(ls); i++ { diffs = append(diffs, ls[i]-ls[i-1]) } for i := 0; i < len(ls)-1; i++ { fmt.Print(ls[i], " (", diffs[i], ") ") } fmt.Println(ls[len(ls)-1]) } fmt.Println()
}
func main() {
fmt.Println("For primes < 1 million:\n") for _, dir := range []string{"ascending", "descending"} { longestSeq(dir) }
}</lang>
- Output:
For primes < 1 million: Longest run(s) of primes with ascending differences is 8 : 128981 (2) 128983 (4) 128987 (6) 128993 (8) 129001 (10) 129011 (12) 129023 (14) 129037 402581 (2) 402583 (4) 402587 (6) 402593 (8) 402601 (12) 402613 (18) 402631 (60) 402691 665111 (2) 665113 (4) 665117 (6) 665123 (8) 665131 (10) 665141 (12) 665153 (24) 665177 Longest run(s) of primes with descending differences is 8 : 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249 752207 (44) 752251 (12) 752263 (10) 752273 (8) 752281 (6) 752287 (4) 752291 (2) 752293
Julia
<lang julia>using Primes
function primediffseqs(maxnum = 1_000_000)
mprimes = primes(maxnum) diffs = map(p -> mprimes[p[1] + 1] - p[2], enumerate(@view mprimes[begin:end-1])) incstart, decstart, bestinclength, bestdeclength = 1, 1, 0, 0 for i in 1:length(diffs)-1 foundinc, founddec = false, false for j in i+1:length(diffs) if !foundinc && diffs[j] <= diffs[j - 1] if (runlength = j - i) > bestinclength bestinclength, incstart = runlength, i end foundinc = true end if !founddec && diffs[j] >= diffs[j - 1] if (runlength = j - i) > bestdeclength bestdeclength, decstart = runlength, i end founddec = true end foundinc && founddec && break end end println("Ascending: ", mprimes[incstart:incstart+bestinclength], " Diffs: ", diffs[incstart:incstart+bestinclength-1]) println("Descending: ", mprimes[decstart:decstart+bestdeclength], " Diffs: ", diffs[decstart:decstart+bestdeclength-1])
end
primediffseqs()
</lang>
- Output:
Ascending: [128981, 128983, 128987, 128993, 129001, 129011, 129023, 129037] Diffs: [2, 4, 6, 8, 10, 12, 14] Descending: [322171, 322193, 322213, 322229, 322237, 322243, 322247, 322249] Diffs: [22, 20, 16, 8, 6, 4, 2]
Lua
This task uses primegen
from: Extensible_prime_generator#Lua
<lang lua>function findcps(primelist, fcmp)
local currlist = {primelist[1]} local longlist, prevdiff = currlist, 0 for i = 2, #primelist do local diff = primelist[i] - primelist[i-1] if fcmp(diff, prevdiff) then currlist[#currlist+1] = primelist[i] if #currlist > #longlist then longlist = currlist end else currlist = {primelist[i-1], primelist[i]} end prevdiff = diff end return longlist
end
primegen:generate(nil, 1000000) cplist = findcps(primegen.primelist, function(a,b) return a>b end) print("ASC ("..#cplist.."): ["..table.concat(cplist, " ").."]") cplist = findcps(primegen.primelist, function(a,b) return a<b end) print("DESC ("..#cplist.."): ["..table.concat(cplist, " ").."]")</lang>
- Output:
ASC (8): [128981 128983 128987 128993 129001 129011 129023 129037] DESC (8): [322171 322193 322213 322229 322237 322243 322247 322249]
Mathematica /Wolfram Language
<lang Mathematica>prime = Prime[Range[PrimePi[10^6]]]; s = Split[Differences[prime], Less]; max = Max[Length /@ s]; diffs = Select[s, Length/*EqualTo[max]]; seqs = SequencePosition[Flatten[s], #, 1]1 & /@ diffs; Take[prime, # + {0, 1}] & /@ seqs
s = Split[Differences[prime], Greater]; max = Max[Length /@ s]; diffs = Select[s, Length/*EqualTo[max]]; seqs = SequencePosition[Flatten[s], #, 1]1 & /@ diffs; Take[prime, # + {0, 1}] & /@ seqs</lang>
- Output:
128981 128983 128987 128993 129001 129011 129023 129037 402581 402583 402587 402593 402601 402613 402631 402691 665111 665113 665117 665123 665131 665141 665153 665177 322171 322193 322213 322229 322237 322243 322247 322249 752207 752251 752263 752273 752281 752287 752291 752293
Nim
<lang Nim>import math, strformat, sugar
const N = 1_000_000
- Erathostenes sieve.
var composite: array[2..N, bool] # Initialized to false i.e. prime.
for n in 2..int(sqrt(float(N))):
if not composite[n]: for k in countup(n * n, N, n): composite[k] = true
let primes = collect(newSeq):
for n in 2..N: if not composite[n]: n
- Longest sequences.
type Order {.pure.} = enum Ascending, Descending
proc longestSeq(order: Order): seq[int] =
## Return the longest sequence for the given order.
let ascending = order == Ascending var currseq: seq[int] prevPrime = 2 diff = if ascending: 0 else: N
for prime in primes: let nextDiff = prime - prevPrime if nextDiff != diff and nextDiff > diff == ascending: currseq.add prime else: if currseq.len > result.len: result = move(currseq) currseq = @[prevPrime, prime] diff = nextDiff prevPrime = prime
if currseq.len > result.len: result = move(currseq)
proc `$`(list: seq[int]): string =
## Return the representation of a list of primes with interleaved differences. var prevPrime: int for i, prime in list: if i != 0: result.add &" ({prime - prevPrime}) " result.addInt prime prevPrime = prime
echo "For primes < 1000000.\n" echo "First longest sequence of consecutive primes with ascending differences:" echo longestSeq(Ascending) echo() echo "First longest sequence of consecutive primes with descending differences:" echo longestSeq(Descending)</lang>
- Output:
For primes < 1000000. First longest sequence of consecutive primes with ascending differences: 128981 (2) 128983 (4) 128987 (6) 128993 (8) 129001 (10) 129011 (12) 129023 (14) 129037 First longest sequence of consecutive primes with descending differences: 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249
Pari/GP
Code is pretty reasonable, runs in ~70 ms at 1,000,000. Running under PARI (starting from gp2c translation) could take advantage of the diff structure of the prime table directly for small cases and avoid substantial overhead, gaining at least a factor of 2 in performance. <lang parigp>showPrecPrimes(p, n)= {
my(v=vector(n)); v[n]=p; forstep(i=n-1,1,-1, v[i]=precprime(v[i+1]-1) ); for(i=1,n, print1(v[i]" "));
} list(lim)= {
my(p=3,asc,dec,ar,dr,arAt=3,drAt=3,last=2); forprime(q=5,lim, my(g=q-p); if(g<last, asc=0; if(desc++>dr, dr=desc; drAt=q ) ,g>last, desc=0; if(asc++>ar, ar=asc; arAt=q ) , asc=desc=0 ); p=q; last=g ); print("Descending differences:"); showPrecPrimes(drAt, dr+2); print("\nAscending differences:"); showPrecPrimes(arAt, ar+2);
} list(10^6)</lang>
- Output:
Descending differences: 322171 322193 322213 322229 322237 322243 322247 322249 Ascending differences: 128981 128983 128987 128993 129001 129011 129023 129037
Perl
<lang perl>use strict; use warnings; use feature 'say'; use ntheory 'primes'; use List::AllUtils <indexes max>;
my $limit = 1000000; my @primes = @{primes( $limit )};
sub runs {
my($op) = @_; my @diff = my $diff = my $run = 1; push @diff, map { my $next = $primes[$_] - $primes[$_ - 1]; if ($op eq '>') { if ($next > $diff) { ++$run } else { $run = 1 } } else { if ($next < $diff) { ++$run } else { $run = 1 } } $diff = $next; $run } 1 .. $#primes;
my @prime_run; my $max = max @diff; for my $r ( indexes { $_ == $max } @diff ) { push @prime_run, join ' ', map { $primes[$r - $_] } reverse 0..$max } @prime_run
}
say "Longest run(s) of ascending prime gaps up to $limit:\n" . join "\n", runs('>'); say "\nLongest run(s) of descending prime gaps up to $limit:\n" . join "\n", runs('<');</lang>
- Output:
Longest run(s) of ascending prime gaps up to 1000000: 128981 128983 128987 128993 129001 129011 129023 129037 402581 402583 402587 402593 402601 402613 402631 402691 665111 665113 665117 665123 665131 665141 665153 665177 Longest run(s) of descending prime gaps up to 1000000: 322171 322193 322213 322229 322237 322243 322247 322249 752207 752251 752263 752273 752281 752287 752291 752293
Phix
integer pn = 1, -- prime numb lp = 2, -- last prime lg = 0, -- last gap pd = 0 -- prev d sequence cr = {0,0}, -- curr run [a,d] mr = {{0},{0}} -- max runs "" while true do pn += 1 integer p = get_prime(pn), gap = p-lp, d = compare(gap,lg) if p>1e6 then exit end if if d then integer i = (3-d)/2 cr[i] = iff(d=pd?cr[i]:lp!=2)+1 if cr[i]>mr[i][1] then mr[i] = {cr[i],pn} end if end if {pd,lp,lg} = {d,p,gap} end while for run=1 to 2 do integer {l,e} = mr[run] sequence p = apply(tagset(e,e-l),get_prime), g = sq_sub(p[2..$],p[1..$-1]) printf(1,"longest %s run length %d: %v gaps: %v\n", {{"ascending","descending"}[run],length(p),p,g}) end for
- Output:
longest ascending run length 8: {128981,128983,128987,128993,129001,129011,129023,129037} gaps: {2,4,6,8,10,12,14} longest descending run length 8: {322171,322193,322213,322229,322237,322243,322247,322249} gaps: {22,20,16,8,6,4,2}
Python
<lang python> from sympy import sieve
primelist = list(sieve.primerange(2,1000000))
listlen = len(primelist)
- ascending
pindex = 1 old_diff = -1 curr_list=[primelist[0]] longest_list=[]
while pindex < listlen:
diff = primelist[pindex] - primelist[pindex-1] if diff > old_diff: curr_list.append(primelist[pindex]) if len(curr_list) > len(longest_list): longest_list = curr_list else: curr_list = [primelist[pindex-1],primelist[pindex]] old_diff = diff pindex += 1
print(longest_list)
- descending
pindex = 1 old_diff = -1 curr_list=[primelist[0]] longest_list=[]
while pindex < listlen:
diff = primelist[pindex] - primelist[pindex-1] if diff < old_diff: curr_list.append(primelist[pindex]) if len(curr_list) > len(longest_list): longest_list = curr_list else: curr_list = [primelist[pindex-1],primelist[pindex]] old_diff = diff pindex += 1
print(longest_list) </lang>
- Output:
[128981, 128983, 128987, 128993, 129001, 129011, 129023, 129037] [322171, 322193, 322213, 322229, 322237, 322243, 322247, 322249]
Raku
<lang perl6>use Math::Primesieve; use Lingua::EN::Numbers;
my $sieve = Math::Primesieve.new;
my $limit = 1000000;
my @primes = $sieve.primes($limit);
sub runs (&op) {
my $diff = 1; my $run = 1;
my @diff = flat 1, (1..^@primes).map: { my $next = @primes[$_] - @primes[$_ - 1]; if &op($next, $diff) { ++$run } else { $run = 1 } $diff = $next; $run; }
my $max = max @diff; my @runs = @diff.grep: * == $max, :k;
@runs.map( { my @run = (0..$max).reverse.map: -> $r { @primes[$_ - $r] } flat roundrobin(@run».&comma, @run.rotor(2 => -1).map({[R-] $_})».fmt('(%d)')); } ).join: "\n"
}
say "Longest run(s) of ascending prime gaps up to {comma $limit}:\n" ~ runs(&infix:«>»);
say "\nLongest run(s) of descending prime gaps up to {comma $limit}:\n" ~ runs(&infix:«<»);</lang>
- Output:
Longest run(s) of ascending prime gaps up to 1,000,000: 128,981 (2) 128,983 (4) 128,987 (6) 128,993 (8) 129,001 (10) 129,011 (12) 129,023 (14) 129,037 402,581 (2) 402,583 (4) 402,587 (6) 402,593 (8) 402,601 (12) 402,613 (18) 402,631 (60) 402,691 665,111 (2) 665,113 (4) 665,117 (6) 665,123 (8) 665,131 (10) 665,141 (12) 665,153 (24) 665,177 Longest run(s) of descending prime gaps up to 1,000,000: 322,171 (22) 322,193 (20) 322,213 (16) 322,229 (8) 322,237 (6) 322,243 (4) 322,247 (2) 322,249 752,207 (44) 752,251 (12) 752,263 (10) 752,273 (8) 752,281 (6) 752,287 (4) 752,291 (2) 752,293
REXX
<lang rexx>/*REXX program finds the longest sequence of consecutive primes where the differences */ /*──────────── between the primes are strictly ascending; also for strictly descending.*/ parse arg hi cols . /*obtain optional argument from the CL.*/ if hi== | hi=="," then hi= 1000000 /* " " " " " " */ if cols== | cols=="," then cols= 10 /* " " " " " " */ call genP /*build array of semaphores for primes.*/ w= 10 /*width of a number in any column. */ call fRun 1; call show 1 /*find runs with ascending prime diffs.*/ call fRun 0; call show 0 /* " " " descending " " */ exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ commas: parse arg ?; do jc=length(?)-3 to 1 by -3; ?=insert(',', ?, jc); end; return ? /*──────────────────────────────────────────────────────────────────────────────────────*/ fRun: parse arg ?; mxrun=0; seq.= /*max run length; lists of prime runs.*/
/*search for consecutive primes < HI.*/ do j=2 for #-2; cp= @.j; jn= j+1 /*CP: current prime; JN: next j */ diff= @.jn - cp /*get difference between last 2 primes.*/ cnt= 1; run= /*initialize the CNT and RUN. */ do k= jn+1 to #-2; km= k-1 /*look for more primes in this run. */ if ? then if @.k-@.km<=diff then leave /*Diff. too small? Stop looking*/ else nop else if @.k-@.km>=diff then leave /* " " large? " " */ run= run @.k; cnt= cnt+1 /*append a prime to the run; bump count*/ diff= @.k - @.km /*calculate difference for next prime. */ end /*k*/ if cnt<=mxrun then iterate /*This run too short? Then keep looking*/ mxrun= max(mxrun, cnt) /*define a new maximum run (seq) length*/ seq.mxrun= cp @.jn run /*full populate the sequence (RUN). */ end /*j*/; return
/*──────────────────────────────────────────────────────────────────────────────────────*/ genP: @.1=2; @.2=3; @.3=5; @.4=7; @.5=11; @.6=13; @.7=17; @.8=19 /*define low primes.*/
#=8; sq.#= @.# ** 2 /*number of primes so far; prime sqiare*/ /* [↓] generate more primes ≤ high.*/ do j=@.#+2 by 2 to hi; parse var j -1 _ /*find odd primes from here on.*/ if _==5 then iterate; if j// 3==0 then iterate /*J ÷ 5? J ÷ by 3? */ if j// 7==0 then iterate; if j//11==0 then iterate /*" " 7? " " " 11? */ if j//13==0 then iterate; if j//17==0 then iterate /*" " 13? " " " 17? */ do k=8 while sq.k<=j /* [↓] divide by the known odd primes.*/ if j // @.k == 0 then iterate j /*Is J ÷ X? Then not prime. ___ */ end /*k*/ /* [↑] only process numbers ≤ √ J */ #= #+1; @.#= j; sq.#= j*j /*bump # of Ps; assign next P; P square*/ end /*j*/; return
/*──────────────────────────────────────────────────────────────────────────────────────*/ show: parse arg ?; if ? then AorD= 'ascending' /*choose which literal for display.*/
else AorD= 'descending' /* " " " " " */ title= ' longest run of consecutive primes whose differences between primes are' , 'strictly' AorD "and < " commas(hi) say; say; say if cols>0 then say ' index │'center(title, 1 + cols*(w+1) ) if cols>0 then say '───────┼'center("" , 1 + cols*(w+1), '─') found= 0; idx= 1 /*initialize # of consecutive primes. */ $= /*a list of consecutive primes (so far)*/ do o=1 for words(seq.mxrun) /*show all consecutive primes in seq. */ c= commas( word(seq.mxrun, o) ) /*obtain the next prime in the sequence*/ found= found + 1 /*bump the number of consecutive primes*/ if cols<=0 then iterate /*build the list (to be shown later)? */ $= $ right(c, max(w, length(c) ) ) /*add a nice prime ──► list, allow big#*/ if found//cols\==0 then iterate /*have we populated a line of output? */ say center(idx, 7)'│' substr($, 2) /*display what we have so far (cols). */ idx= idx + cols; $= /*bump the index count for the output*/ end /*o*/ if $\== then say center(idx, 7)"│" substr($, 2) /*maybe show residual output*/ if cols>0 then say '───────┴'center("" , 1 + cols*(w+1), '─') say; say commas(Cprimes) ' was the'title; return</lang>
- output when using the default inputs:
index │ longest run of consecutive primes whose differences between primes are strictly ascending and < 1,000,000 ───────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────── 1 │ 128,981 128,983 128,987 128,993 129,001 129,011 129,023 129,037 ───────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────── 8 was the longest run of consecutive primes whose differences between primes are strictly ascending and < 1,000,000 index │ longest run of consecutive primes whose differences between primes are strictly descending and < 1,000,000 ───────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────── 1 │ 322,171 322,193 322,213 322,229 322,237 322,243 322,247 322,249 ───────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────── 8 was the longest run of consecutive primes whose differences between primes are strictly descending and < 1,000,000
Ruby
<lang ruby>require "prime" limit = 1_000_000
puts "First fount longest run of ascending prime gaps up to #{limit}:" p Prime.each(limit).each_cons(2).chunk_while{|(i1,i2), (j1,j2)| j1-i1 < j2-i2 }.max_by(&:size).flatten.uniq puts "\nFirst fount longest run of descending prime gaps up to #{limit}:" p Prime.each(limit).each_cons(2).chunk_while{|(i1,i2), (j1,j2)| j1-i1 > j2-i2 }.max_by(&:size).flatten.uniq</lang>
- Output:
First fount longest run of ascending prime gaps up to 1000000: [128981, 128983, 128987, 128993, 129001, 129011, 129023, 129037] First fount longest run of descending prime gaps up to 1000000: [322171, 322193, 322213, 322229, 322237, 322243, 322247, 322249]
Rust
<lang rust>// [dependencies] // primal = "0.3"
fn print_diffs(vec: &[usize]) {
for i in 0..vec.len() { if i > 0 { print!(" ({}) ", vec[i] - vec[i - 1]); } print!("{}", vec[i]); } println!();
}
fn main() {
let limit = 1000000; let mut asc = Vec::new(); let mut desc = Vec::new(); let mut max_asc = Vec::new(); let mut max_desc = Vec::new(); let mut max_asc_len = 0; let mut max_desc_len = 0; for p in primal::Sieve::new(limit) .primes_from(2) .take_while(|x| *x < limit) { let alen = asc.len(); if alen > 1 && p - asc[alen - 1] <= asc[alen - 1] - asc[alen - 2] { asc = asc.split_off(alen - 1); } asc.push(p); if asc.len() >= max_asc_len { if asc.len() > max_asc_len { max_asc_len = asc.len(); max_asc.clear(); } max_asc.push(asc.clone()); } let dlen = desc.len(); if dlen > 1 && p - desc[dlen - 1] >= desc[dlen - 1] - desc[dlen - 2] { desc = desc.split_off(dlen - 1); } desc.push(p); if desc.len() >= max_desc_len { if desc.len() > max_desc_len { max_desc_len = desc.len(); max_desc.clear(); } max_desc.push(desc.clone()); } } println!("Longest run(s) of ascending prime gaps up to {}:", limit); for v in max_asc { print_diffs(&v); } println!("\nLongest run(s) of descending prime gaps up to {}:", limit); for v in max_desc { print_diffs(&v); }
}</lang>
- Output:
Longest run(s) of ascending prime gaps up to 1000000: 128981 (2) 128983 (4) 128987 (6) 128993 (8) 129001 (10) 129011 (12) 129023 (14) 129037 402581 (2) 402583 (4) 402587 (6) 402593 (8) 402601 (12) 402613 (18) 402631 (60) 402691 665111 (2) 665113 (4) 665117 (6) 665123 (8) 665131 (10) 665141 (12) 665153 (24) 665177 Longest run(s) of descending prime gaps up to 1000000: 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249 752207 (44) 752251 (12) 752263 (10) 752273 (8) 752281 (6) 752287 (4) 752291 (2) 752293
Sidef
<lang ruby>func runs(f, arr) {
var run = 0 var diff = 0 var diffs = []
arr.each_cons(2, {|p1,p2| var curr_diff = (p2 - p1) f(curr_diff, diff) ? ++run : (run = 1) diff = curr_diff diffs << run })
var max = diffs.max var runs = []
diffs.indices_by { _ == max }.each {|i| runs << arr.slice(i - max + 1, i + 1) }
return runs
}
var limit = 1e6 var primes = limit.primes
say "Longest run(s) of ascending prime gaps up to #{limit.commify}:" say runs({|a,b| a > b }, primes).join("\n")
say "\nLongest run(s) of descending prime gaps up to #{limit.commify}:" say runs({|a,b| a < b }, primes).join("\n")</lang>
- Output:
Longest run(s) of ascending prime gaps up to 1,000,000: [128981, 128983, 128987, 128993, 129001, 129011, 129023, 129037] [402581, 402583, 402587, 402593, 402601, 402613, 402631, 402691] [665111, 665113, 665117, 665123, 665131, 665141, 665153, 665177] Longest run(s) of descending prime gaps up to 1,000,000: [322171, 322193, 322213, 322229, 322237, 322243, 322247, 322249] [752207, 752251, 752263, 752273, 752281, 752287, 752291, 752293]
Wren
<lang ecmascript>import "/math" for Int
var LIMIT = 999999 var primes = Int.primeSieve(LIMIT)
var longestSeq = Fn.new { |dir|
var pd = 0 var longSeqs = 2 var currSeq = [2] for (i in 1...primes.count) { var d = primes[i] - primes[i-1] if ((dir == "ascending" && d <= pd) || (dir == "descending" && d >= pd)) { if (currSeq.count > longSeqs[0].count) { longSeqs = [currSeq] } else if (currSeq.count == longSeqs[0].count) longSeqs.add(currSeq) currSeq = [primes[i-1], primes[i]] } else { currSeq.add(primes[i]) } pd = d } if (currSeq.count > longSeqs[0].count) { longSeqs = [currSeq] } else if (currSeq.count == longSeqs[0].count) longSeqs.add(currSeq) System.print("Longest run(s) of primes with %(dir) differences is %(longSeqs[0].count):") for (ls in longSeqs) { var diffs = [] for (i in 1...ls.count) diffs.add(ls[i] - ls[i-1]) for (i in 0...ls.count-1) System.write("%(ls[i]) (%(diffs[i])) ") System.print(ls[-1]) } System.print()
}
System.print("For primes < 1 million:\n") for (dir in ["ascending", "descending"]) longestSeq.call(dir)</lang>
- Output:
For primes < 1 million: Longest run(s) of primes with ascending differences is 8: 128981 (2) 128983 (4) 128987 (6) 128993 (8) 129001 (10) 129011 (12) 129023 (14) 129037 402581 (2) 402583 (4) 402587 (6) 402593 (8) 402601 (12) 402613 (18) 402631 (60) 402691 665111 (2) 665113 (4) 665117 (6) 665123 (8) 665131 (10) 665141 (12) 665153 (24) 665177 Longest run(s) of primes with descending differences is 8: 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249 752207 (44) 752251 (12) 752263 (10) 752273 (8) 752281 (6) 752287 (4) 752291 (2) 752293
XPL0
<lang XPL0>func IsPrime(N); \Return 'true' if N > 2 is a prime number int N, I; [if (N&1) = 0 \even number\ then return false; for I:= 3 to sqrt(N) do
[if rem(N/I) = 0 then return false; I:= I+1; ];
return true; ];
proc ShowSeq(Dir, Str); \Show longest sequence of distances between primes int Dir, Str; int Count, MaxCount, N, P, P0, D, D0, I, AP(1000), MaxAP(1000); [Count:= 0; MaxCount:= 0; P0:= 2; D0:= 0; \preceding prime and distance AP(Count):= P0; Count:= Count+1; for N:= 3 to 1_000_000-1 do
if IsPrime(N) then [P:= N; \got a prime number D:= P - P0; \distance from preceding prime if D*Dir > D0*Dir then [AP(Count):= P; Count:= Count+1; if Count > MaxCount then \save best sequence [MaxCount:= Count; for I:= 0 to MaxCount-1 do MaxAP(I):= AP(I); ]; ] else [Count:= 0; \restart sequence AP(Count):= P0; Count:= Count+1; \possible beginning AP(Count):= P; Count:= Count+1; ]; P0:= P; D0:= D; ];
Text(0, "Longest sequence of "); Text(0, Str); Text(0, " distances between primes: "); IntOut(0, MaxCount); CrLf(0); for I:= 0 to MaxCount-2 do
[IntOut(0, MaxAP(I)); Text(0, " ("); IntOut(0, MaxAP(I+1) - MaxAP(I)); Text(0, ") "); ];
IntOut(0, MaxAP(I)); CrLf(0); ];
[ShowSeq(+1, "ascending"); \main
ShowSeq(-1, "descending");
]</lang>
- Output:
Longest sequence of ascending distances between primes: 8 128981 (2) 128983 (4) 128987 (6) 128993 (8) 129001 (10) 129011 (12) 129023 (14) 129037 Longest sequence of descending distances between primes: 8 322171 (22) 322193 (20) 322213 (16) 322229 (8) 322237 (6) 322243 (4) 322247 (2) 322249