2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,16 +1,19 @@
The task is to write a generator of prime numbers, in order, that will automatically adjust to accommodate the generation of any reasonably high prime.
;Task:
Write a generator of prime numbers, in order, that will automatically adjust to accommodate the generation of any reasonably high prime.
The routine should demonstrably rely on either:
# Being based on an open-ended counter set to count without upper limit other than system or programming language limits. In this case, explain where this counter is in the code.
# Being based on a limit that is extended automatically. In this case, choose a small limit that ensures the limit will be passed when generating some of the values to be asked for below.
# If other methods of creating an extensible prime generator are used, the algorithm's means of extensibility/lack of limits should be stated.
The routine should be used to:
* Show the first twenty primes.
* Show the primes between 100 and 150.
* Show the ''number'' of primes between 7,700 and 8,000.
* Show the 10,000th prime.
<br>
Show output on this page.
'''Note:''' You may reference code already on this site if it is written to be imported/included, then only the code necessary for import and the performance of this task need be shown. (It is also important to leave a forward link on the referenced tasks entry so that later editors know that the code is used for multiple tasks).
@ -19,3 +22,4 @@ Show output on this page.
;See also:
* The task is written so it may be useful in solving task [[Emirp primes]] as well as others (depending on its efficiency).
<br><br>

View file

@ -0,0 +1,50 @@
ns test-project-intellij.core
(:gen-class)
(:require [clojure.string :as string]))
(def primes
" The following routine produces a infinite sequence of primes
(i.e. can be infinite since the evaluation is lazy in that it
only produces values as needed). The method is from clojure primes.clj library
which produces primes based upon O'Neill's paper:
'The Genuine Sieve of Eratosthenes'.
Produces primes based upon trial division on previously found primes up to
(sqrt number), and uses 'wheel' to avoid
testing numbers which are divisors of 2, 3, 5, or 7.
A full explanation of the method is available at:
[https://github.com/stuarthalloway/programming-clojure/pull/12] "
(concat
[2 3 5 7]
(lazy-seq
(let [primes-from ; generates primes by only checking if primes
; numbers which are not divisible by 2, 3, 5, or 7
(fn primes-from [n [f & r]]
(if (some #(zero? (rem n %))
(take-while #(<= (* % %) n) primes))
(recur (+ n f) r)
(lazy-seq (cons n (primes-from (+ n f) r)))))
; wheel provides offsets from previous number to insure we are not landing on a divisor of 2, 3, 5, 7
wheel (cycle [2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2
6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6
2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10])]
(primes-from 11 wheel)))))
(defn between [lo hi]
"Primes between lo and hi value "
(->> (take-while #(<= % hi) primes)
(filter #(>= % lo))
))
(println "First twenty:" (take 20 primes))
(println "Between 100 and 150:" (between 100 150))
(println "Number between 7,7700 and 8,000:" (count (between 7700 8000)))
(println "10,000th prime:" (nth primes (dec 10000))) ; decrement by one since nth starts counting from 0
}

View file

@ -0,0 +1,4 @@
DO WHILE(F*F <= LST) !But, F*F might overflow the integer limit so instead,
DO WHILE(F <= LST/F) !Except, LST might also overflow the integer limit, so
DO WHILE(F <= (IST + 2*(SBITS - 1))/F) !Which becomes...
DO WHILE(F <= IST/F + (MOD(IST,F) + 2*(SBITS - 1))/F) !Preserving the remainder from IST/F.

View file

@ -0,0 +1,382 @@
MODULE PRIMEBAG !Need prime numbers? Plenty are available.
C Creates and expands a disc file for a sieve of Eratoshenes, representing odd numbers only and starting with three.
C Storage requirements: an array of N prime numbers in 16/32/64 bits vs. a bit array up to the 16/32/64 bit limit.
C Word size N Prime N words in bits Bit array in bits.
C 8 bit P(31) = 127 248 128
C P(54) = 251 432 256
C 16 bit P(3,512) = 32,749 56,192 32,768
C P(6,542) = 65,521 104,672 65,536
C 32 bit P(105,097,565) = 2,147,483,647 3,363,122,080 2,147,483,648
C P(203,280,221) = 4,294,967,291 6,504,967,072 4,294,967,296
C 64 bit 2.112E17 ? 1.352E19 9,223,372,036,854,775,808 ~ 9.22E18
C from n/Ln(n) 4.158E17 ? 2.661E19 18,446,744,073,709,551,616 ~ 1.84E19
INTEGER MSG !I/O unit number.
INTEGER SSTASH !For attachment to my stash file.
INTEGER SRECLEN,SCHARS,SBITS !Sizes.
INTEGER SORG !Where the sieve starts. This must be three.
INTEGER SLAST !Last record in my stash file.
DATA SSTASH,SREC,SLAST/0,0,0/ !Prepared by PRIMEBAG.
PARAMETER (SRECLEN = 1024) !4K disc bloc size, but RECL (in OPEN) is in terms of four-byte integers.
PARAMETER (SCHARS = (SRECLEN - 1)*4) !Reserving space for one number at the start.
PARAMETER (SBITS = SCHARS*8) !Known size of a character.
PARAMETER (SORG = 3) !First odd number past two, which is not odd.
CHARACTER*(*) SFILE !A name is needed.
PARAMETER (SFILE = "C:/Nicky/RosettaCode/Primes/PrimeSieve.bit") !I don't have to count the characters.
Components of a buffered record for the stash.
INTEGER SREC !The record number.
CHARACTER*1 C4(4) !The start of the record - a counter.
CHARACTER*1 SCHAR(0:SCHARS - 1) !The majority of the record - a bit array, packed in 8-bit blobs...
Collect some bit twiddling assistants for AND and OR, rather than bit shifting.
CHARACTER*1 BITON(0:7),BITOFF(0:7) !Functions IBSET and IBCLR may not be available, and are little-endian anyway.
PARAMETER (BITON =(/CHAR(2#10000000),CHAR(2#01000000), !128, 64, Reading strictly left-to-right.
1 CHAR(2#00100000),CHAR(2#00010000), ! 32, 16, Uncompromising bigendery.
1 CHAR(2#00001000),CHAR(2#00000100), ! 8, 4, Not just for bytes in words,
3 CHAR(2#00000010),CHAR(2#00000001)/)) ! 2, 1. But also bits in bytes.
PARAMETER (BITOFF=(/CHAR(2#01111111),CHAR(2#10111111), !127, 191, BITON + BITOFF = 255.
2 CHAR(2#11011111),CHAR(2#11101111), !223, 239,
1 CHAR(2#11110111),CHAR(2#11111011), !247, 251,
3 CHAR(2#11111101),CHAR(2#11111110)/)) !253, 254.
CONTAINS
INTEGER FUNCTION I4UNPACK(C4) !Convert four successive characters into an integer.
CHARACTER*1 C4(4) !The characters.
I4UNPACK = ((ICHAR(C4(1))*256 + ICHAR(C4(2)))*256 !Convert the first four bytes
1 + ICHAR(C4(3)))*256 + ICHAR(C4(4)) !To a four-byte integer.
END FUNCTION I4UNPACK !Big-endian style, irrespective of cpu endianness.
SUBROUTINE C4PACK(I4) !Convert an integer into successive bytes.
Could return the result via a fancy function, but for now a global variable will do.
INTEGER I4,N !The integer, and a copy to damage.
INTEGER I !A stepper.
N = I4 !Keep the original safe.
DO I = 4,1,-1 !Know that four characters will do. Fixed format makes this easy.
C4(I) = CHAR(MOD(N,256)) !Grab the low-order eight bits.
N = N/256 !And shift right eight.
END DO !Do it again.
END SUBROUTINE C4PACK !Stored big-endianly, irrespective of cpu endianness.
LOGICAL FUNCTION GRASPPRIMEBAG(F)
INTEGER F !The I/O unit number to use.
LOGICAL EXIST !Use the keyword as a name
INTEGER IOSTAT !And don't worry over assignment direction.
CHARACTER*3 STYLE !One way or another.
SSTASH = F !I shall use it.
INQUIRE (FILE = SFILE,EXIST = EXIST) !Trouble with a missing "path" may arise.
IF (EXIST) THEN !If the file exists,
STYLE = "OLD" !I shall read it.
ELSE !But if it doesn't,
STYLE = "NEW" !I shall create it.
END IF !Enough prevarication.
OPEN(SSTASH,FILE = SFILE, STATUS = STYLE, !Go for the file.
& ACCESS = "DIRECT", RECL = SRECLEN, FORM = "UNFORMATTED", !I have plans.
& ERR = 666, IOSTAT = IOSTAT) !Which may be thwarted.
IF (EXIST) THEN !If there is one...
CALL READSCHAR(1) !The first record is also a header.
SLAST = I4UNPACK(C4) !The number of records stored.
ELSE !Otherwise, start from scratch.
SLAST = 0 !No saved records.
CALL PSURGE(SCHAR) !During preparation of the first batch of bits.
END IF !All should now be in readiness.
GRASPPRIMEBAG = .TRUE.!So, feel confidence.
RETURN !And escape.
666 WRITE (*,667) IOSTAT,SFILE !But, something may have gone wrong.
667 FORMAT ("Pox! Error code ",I0, !A "hole" in the directory path?
1 " when attempting to open file ",A) !Read-only access allowed when I want "update"?
GRASPPRIMEBAG = .FALSE. !Whatever, it didn't work.
END FUNCTION GRASPPRIMEBAG !So much for that.
SUBROUTINE READSCHAR(R) !Get record R into SCHAR, which may already hold it.
INTEGER R !The record number desired.
IF (R.EQ.SREC) RETURN !Perhaps it is already to hand.
SREC = R !If not, move attention to it.
READ (SSTASH,REC = SREC) C4,SCHAR !And read the record.
END SUBROUTINE READSCHAR!Thus, I have a buffer too.
LOGICAL FUNCTION PSURGE(BIT8) !Add another record to the stash.
C Surges forward into the next batch of primes, to be stored via a bit array in the file.
C Each record starts with a count of the number of primes that have gone before.
C Except that for the first record, this is the record counter for the stash file.
C Except that when starting the second record, one is also the number of primes before SORG.
CHARACTER*1 BIT8(0:SCHARS - 1) !Watch out! This may be SCHAR itself!
INTEGER IST,LST !The numbers spanned by the surge.
INTEGER F !A factor.
INTEGER I !Another factor and a stepper.
INTEGER C !Index for array BIT8.
INTEGER NP !Number of primes.
Carry forward the count of previous primes to start the following record..
10 IF (SLAST.GT.0) THEN !Is there a previous record?
CALL READSCHAR(SLAST) !Yes. Grab it. A good chance this is already in C4,SCHAR.
NP = I4UNPACK(C4) !Its count of the primes accumulated before it.
DO I = 0,SCHARS - 1 !Find out how namy primes it fingered by scanning its bits.
NP = NP + COUNT(IAND(ICHAR(SCHAR(I)),ICHAR(BITON)).NE.0) !Whee! Eight at a go!
END DO !On to the next byte.
END IF !When creating a new record, its follower may not be sought in this run.
Concoct the next batch of bits. Contorted calculations avoid integer overflow.
20 BIT8 = CHAR(255) !All bits are aligned with numbers that might prove to be prime.
IST = SORG + SLAST*(2*SBITS) !Bit(0) of BIT8(0) corresponds to IST.
LST = IST + 2*(SBITS - 1) !Bit(last) to this number. Remember, only odd numbers have bits.
IF (IST.LE.0) THEN !Humm. I'd better check.
WRITE (MSG,21) SLAST,IST,LST !This works only with two's complement integers.
21 FORMAT (/,"Integer overflow in the sieve of Eratosthenes!", !Oh dear.
1 /,"Advancing from surge ",I0," to span ",I0," to ",I0) !These numbers will look odd.
PSURGE = .FALSE. !But it is better than no indication of what went wrong.
RETURN !Give in.
END IF !Enough worrying.
F = 3 !The first possible factor. Zapping will start at F²
c DO WHILE(F.LE.LST/F) !If F² is past the end, so will be still larger F: enough.
DO WHILE(F.LE.IST/F + (MOD(IST,F) + 2*(SBITS - 1))/F) !"Synthetic division" avoiding overflow.
I = (IST - 1)/F + 1 !I want the first multiple of F in IST:LST. F may be a factor of IST.
IF (MOD(I,2).EQ.0) I = I + 1!If even, advance to the next odd multiple. Even numbers are omitted by design.
IF (I.LT.F) I = F !Less than F is superfluous: the position was zapped by earlier action.
c I = (I*F - IST)/2 !Current bit positions are for IST, IST+2, IST+4, etc.
I = ((I - IST/F)*F - MOD(IST,F))/2 !Avoids overflow when calculating the start value, I*F.
DO I = I,SBITS - 1,F !Zap every F'th bit along. This is the sieve of Eratosthenes.
C = I/8 !Eight bits per character.
BIT8(C) = CHAR(IAND(ICHAR(BIT8(C)), !For F = 3 and 5, characters will be hit more than once.
1 ICHAR(BITOFF(MOD(I,8))))) !Whack a bit. All the above just for this!
END DO !On to the next bit.
22 F = NEXTPRIME(F) !So much for F. Next, please.
END DO !Are we there yet?
Correct the count in the header, if this is an added record.
30 IF (SLAST.GT.0) THEN !So, was there a pre-existing header record?
CALL READSCHAR(1) !Yes. Get the header record into C4,SCHAR.
CALL C4PACK(SLAST + 1) !This is the new record count.
WRITE (SSTASH,REC = 1) C4,SCHAR !Write it all back.
SCHAR = BIT8 !Ensure that SCHAR and SREC will be agreed.
END IF !So much for the header's count.
Cast the bits into the stash by writing record SLAST + 1..
40 IF (SLAST.EQ.0) THEN !If we're writing the first record,
CALL C4PACK(1) !Then this is the record count.
ELSE !Otherwise,
CALL C4PACK(NP) !Place the previous primes count.
END IF !All this to help PRIME(i).
SLAST = SLAST + 1 !This is now the last stashed record.
WRITE (SSTASH,REC = SLAST) C4,BIT8 !I/O directly from the work area?
SREC = SLAST !This is where BIT8 was written.
PSURGE = .TRUE. !That assumes BIT8 is not SCHAR for SLAST > 1.
END FUNCTION PSURGE !That was fun!
RECURSIVE SUBROUTINE GETSREC(R) !Make present the bit array belonging to record R.
INTEGER R !The record number..
CHARACTER*1 BIT8(0:SCHARS - 1) !A scratchpad. Others may be relying on SCHAR.
IF (SLAST.LE.0) RETURN!DANGER! The first record is being initialised!
DO WHILE(SLAST.LT.R) !If we haven't reached so far,
IF (.NOT.PSURGE(BIT8)) THEN !Slog forwards one record's worth.
WRITE (MSG,1) R !Or maybe not.
1 FORMAT ("Cannot prepare surge ",I0) !Explain.
STOP "No bits, no go." !And quit.
END IF !And having prepared the next block of bits,
END DO !Check afresh.
CALL READSCHAR(R) !Read the desired record's bits.
END SUBROUTINE GETSREC !Done.
INTEGER FUNCTION PRIME(N) !P(1) = 2, P(2) = 3, etc.
C Calculate P(n) ~ n.ln(n)
C ~ n{ln(n) + ln(ln(n)) - 1 + (ln(ln(n)) - 2)/ln(n) - [ln(ln(n))**2 - 6*log(log(n)) + 11]/[2*(ln(n))**2] + ....}
C J.B.Rosser's 1938 Theorem: n[ln(n) + ln(ln(n)) - 1] < P(n) < n[ln(n) + ln(ln(n))]
C or, with E = ln(n) + ln(ln(n)), n[E - 1] < P(n) < n[E]
C Experimentation shows that the undershoot of the first two terms involves many records worth of bits.
C Including additional terms does much better, but can overshoot.
INTEGER N !The desired one.
INTEGER R,NP !Counts.
INTEGER B,C !Bit and character indices.
DOUBLE PRECISION EST,LN,LLN !Hope, if not actuality.
IF (N.LE.0) STOP "Primes are counted positively!" !Something must be wrong!
IF (N.LE.1) THEN !The start of the bit array being preempted.
PRIME = 2 !So, no array access.
ELSE !Otherwise, the fun begins.
LN = LOG(DFLOAT(N)) !Here we go.
LLN = LOG(LN) !A popular term.
EST = N*(LN !Estimate the value of the N'th prime.
1 + LLN - 1 !Second term
2 + (LLN - 2)/LN !Third term.
3 - (LLN**2 - 6*LLN + 11)/(2*LN**2)) !Fourth term.
R = (EST - SORG)/(2*SBITS) + 1 !Thereby selecting a record to scan.
IF (R.LE.0) R = 1 !And not making a mess with N < 6 or so.
9 CALL GETSREC(R) !Go for the record.
IF (R.LE.1) THEN !The first record starts with the record count.
NP = 1 !And I know how many primes precede its start point
ELSE !While for all subsequent records,
NP = I4UNPACK(C4) !This counts the number of primes that precede record R's start number.
END IF !So now I'm ready to count onwards.
IF (N.LE.NP) THEN !Maybe not.
R = R - 1 !The estimate took me too far ahead.
GO TO 9 !Try again.
END IF !Could escalate to a binary search or even an interpolating search.
Commence scanning the bits.
C = 0 !Start with the first character of SREC..
B = -1 !Syncopation. The formula is known to always under-estimate.
10 IF (NP.LT.N) THEN !Are we there yet?
11 B = B + 1 !No. Advance to the next bit.
IF (B.GE.8) THEN !Overflowed a character yet?
B = 0 !Yes. Start afresh at the first bit.
C = C + 1 !And advance one character.
IF (C.GE.SCHARS) THEN !Overflowed the record yet?
C = 0 !Yes. Start afresh at its first character.
R = R + 1 !And advance to the next record.
CALL GETSREC(R) !Possibly, create it.
END IF !So much for records.
END IF !We're now ready to test bit B of character C of record R.
IF (IAND(ICHAR(SCHAR(C)),ICHAR(BITON(B))).EQ.0) GO TO 11 !Not a prime. Search on.
NP = NP + 1 !Count another prime.
GO TO 10 !Pehaps this will be the one.
END IF !So much for the search.
PRIME = SORG + (R - 1)*(2*SBITS) + (C*8 + B)*2 !The corresponding number.
IF (PRIME.LE.0) WRITE (MSG,666) N,PRIME !Or, possibly not.
666 FORMAT ("Integer overflow! Prime(",I0,") gives ",I0,"!") !Let us hope the caller notices.
END IF !So, all going well,
END FUNCTION PRIME !It is found.
RECURSIVE INTEGER FUNCTION NEXTPRIME(N) !Keep right on to the end of the road.
Can invoke GETSREC, which can invoke PSURGE, which ... invokes NEXTPRIME. Oh dear.
INTEGER N !Not necessarily itself a prime number.
INTEGER NN !A value to work with.
INTEGER R !A record number into the stash.
INTEGER I,IST !Number offsets.
INTEGER C,B !Character and bit index.
IF (N.LE.1) THEN !Suspicion prevails.
NN = 2 !This is not represented in my bit array.
ELSE !Otherwise, the fun begins.
NN = N + 1 !Advance, with a copy I can mess with.
IF (MOD(NN,2).EQ.0) NN = NN + 1 !Thus, NN is now odd.
IF (NN.LE.0) GO TO 666 !But perhaps not proper, due to overflow.
R = (NN - SORG)/(2*SBITS) !SORG is odd, so (NN - SORG) is even.
CALL GETSREC(R + 1) !The first record is numbered one, not zero.
IST = SORG + R*(2*SBITS) !The number for its first bit: even numbers are omitted..
I = (NN - IST)/2 !Offset into the record. NN - IST is even.
C = I/8 !Which character in SCHAR(0:SCHARS - 1)?
B = MOD(I,8) !Which bit in SCHAR(C)?
10 IF (IAND(ICHAR(SCHAR(C)),ICHAR(BITON(B))).EQ.0) THEN !On for a prime.
NN = NN + 2 !Alas, it is off, so NN is not a prime. Perhaps this will be.
B = B + 1 !Advance one bit. Each bit steps two.
IF (B.GE.8) THEN !Past the end of the character?
B = 0 !Yes. Back to bit zero.
C = C + 1 !And advance one chracter.
IF (C.GE.SCHARS) THEN !Past the end of the record?
IF (NN.LE.0) GO TO 666!Yes. If NN has overflowed, the end of the rope is reached.
C = 0 !Back to the start of a record.
R = R + 1 !Advance one record.
CALL GETSREC(R + 1) !And read it. (Count is from 1, not 0).
END IF !So much for overflowing a record.
END IF !So much for overflowing a character.
GO TO 10 !Try again.
END IF !So much for the bit array.
END IF !If there had been a scan.
NEXTPRIME = NN !The number for which the scan stopped.
IF (NN.GT.0) RETURN !All is well.
666 WRITE (MSG,667) N,NN !Or, maybe not. Careful: this won't appear if NEXTPRIME is invoked in a WRITE list.
667 FORMAT ("Integer overflow! NextPrime(",I0,") gives ",I0,"!") !The recipient could do a two's complement.
NEXTPRIME = NN !Prefer to return the bad value rather than fail to return anything.
END FUNCTION NEXTPRIME !No divisions, no sieving. Here, anyway
INTEGER FUNCTION PREVIOUSPRIME(N) !If N is good, this can't overflow.
INTEGER N !The number, not necessarily a prime.
INTEGER NN !A value to mess with.
INTEGER R !A record number.
INTEGER I !Offset.
INTEGER C,B !Character and bit fingers.
IF (N.LE.3) THEN !Suppress annoyances.
NN = 2 !This is now called the first prime, not one.
ELSE !Otherwise, some work is to be done.
NN = N - 1 !Step back one to ensure previousness.
IF (MOD(NN,2).EQ.0) NN = NN - 1 !And here, oddness is a minimal requirement.
R = (NN - SORG)/(2*SBITS) !Finger the record containing the bit for NN.
CALL GETSREC(R + 1) !Record counting starts with one.
I = (NN - (SORG + R*(2*SBITS)))/2 !Offset into that record.
C = I/8 !Finger the character in SCHAR.
B = MOD(I,8) !And the bit within the character.
10 IF (IAND(ICHAR(SCHAR(C)),ICHAR(BITON(B))).EQ.0) THEN !On for a prime.
NN = NN - 2 !Alas, it is off, so NN is not a prime. Perhaps this will be.
B = B - 1 !Retreat one bit. Each bit steps two.
IF (B.LT.0) THEN !Past the start of the character?
B = 7 !Yes. Back to the last bit.
C = C - 1 !And retreat one chracter.
IF (C.LT.0) THEN !Past the start of the record?
C = SCHARS - 1 !Yes. Back to the end of a record.
R = R - 1 !Retreat one record.
CALL GETSREC(R + 1) !And read it. (Count is from 1, not 0).
END IF !So much for overflowing a record.
END IF !So much for overflowing a character.
GO TO 10 !Try again.
END IF !So much for the bit array.
END IF !Possibly, it was not needed.
PREVIOUSPRIME = NN !There.
END FUNCTION PREVIOUSPRIME !Doesn't overflow, either.
LOGICAL FUNCTION ISPRIME(N) !Could fool around explicity testing 2 and 3 and say 5,
INTEGER N !But that means also checking that N > 2, N > 3, and N > 5.
ISPRIME = N .EQ. NEXTPRIME(N - 1) !This is so much easier.
END FUNCTION ISPRIME !No divisions up to SQRT(N) or the like either.
END MODULE PRIMEBAG !Functions updating a disc file as a side effect...
PROGRAM POKE
USE PRIMEBAG
INTEGER I,P,N,N1,N2 !Assorted assistants.
INTEGER ORDER !A collection of special values.
PARAMETER (ORDER = 6) !For one, two, and four byte integers.
INTEGER EDGE(ORDER) !Considered as two's complement and unsigned.
PARAMETER (EDGE = (/31,54,3512,6542,105097565,203280221/)) !These primes are of interest.
MSG = 6 !Standard output.
IF (.NOT.GRASPPRIMEBAG(66)) STOP "Gan't grab my file!" !Attempt in hope.
Case 1.
C FORALL(I = 1:20) LIST(I) = PRIME(I) is rejected because function Prime(i) is rather impure.
10 WRITE (MSG,11)
11 FORMAT (19X,"First twenty primes: ", $)
DO I = 1,20
P = PRIME(I)
WRITE (MSG,12) P
12 FORMAT (I0,",",$)
END DO
Case 2.
20 WRITE (MSG,21)
21 FORMAT (/,12X,"Primes between 100 and 150: ",$)
P = 100
22 P = NEXTPRIME(P) !While (P:=NextPrime(P)) <= 150 do Print P;
IF (P.LE.150) THEN !But alas, no assignment within an expression.
WRITE (MSG,23) P
23 FORMAT (I0,",",$)
GO TO 22
END IF
Case 3.
30 N1 = 7700 !Might as well parameterise this.
N2 = 8000 !Rather than litter the source with explicit integers.
N = 0
P = N1
31 P = NEXTPRIME(P)
IF (P.LE.N2) THEN
N = N + 1
GO TO 31
END IF
WRITE (MSG,32) N1,N2,N
32 FORMAT (/"Number of primes between ",I0," and ",I0,": ",I0)
Case 4.
40 WRITE (MSG,41)
41 FORMAT (/,"Tenfold steps...")
N = 1
DO I = 1,9 !This goes about as far as it can go.
P = PRIME(N)
WRITE (MSG,42) N,P
42 FORMAT ("Prime(",I0,") = ",I0)
N = N*10
END DO
Cast forth some interesting values.
100 WRITE (MSG,101)
101 FORMAT (/,"Primes close to number sizes")
DO N = 1,ORDER !Step through the list.
N1 = EDGE(N) - 1 !Syncopation for the special value.
DO I = 1,2 !I want the prime on either side.
N1 = N1 + 1 !So, there are two successive primes to finger.
WRITE (MSG,102) N1 !Identify the index.
102 FORMAT ("Prime(",I0,") = ",$) !Piecemeal writing to the output,
P = PRIME(N1) !As this may fling forth a complaint.
WRITE (MSG,103) P !Show the value returned.
103 FORMAT (I0,", ",$) !Which may be unexpected.
END DO !On to the second.
WRITE (MSG,*) !End the line after the second result.
END DO !On to the next in the list.
END !Whee!

View file

@ -0,0 +1,5 @@
P = NEXTPRIME(100)
DO WHILE (P.LE.150)
...stuff...
P = NEXTPRIME(P)
END DO

View file

@ -0,0 +1 @@
P:=100; WHILE (P:=NextPrime(P)) <= 150 DO stuff;

View file

@ -0,0 +1,41 @@
function primeGenerator(num, showPrimes) {
var i,
arr = [];
function isPrime(num) {
// try primes <= 16
if (num <= 16) return (
num == 2 || num == 3 || num == 5 || num == 7 || num == 11 || num == 13
);
// cull multiples of 2, 3, 5 or 7
if (num % 2 == 0 || num % 3 == 0 || num % 5 == 0 || num % 7 == 0)
return false;
// cull square numbers ending in 1, 3, 7 or 9
for (var i = 10; i * i <= num; i += 10) {
if (num % (i + 1) == 0) return false;
if (num % (i + 3) == 0) return false;
if (num % (i + 7) == 0) return false;
if (num % (i + 9) == 0) return false;
}
return true;
}
if (typeof num == "number") {
for (i = 0; arr.length < num; i++) if (isPrime(i)) arr.push(i);
// first x primes
if (showPrimes) return arr;
// xth prime
else return arr.pop();
}
if (Array.isArray(num)) {
for (i = num[0]; i <= num[1]; i++) if (isPrime(i)) arr.push(i);
// primes between x .. y
if (showPrimes) return arr;
// number of primes between x .. y
else return arr.length;
}
// throw a default error if nothing returned yet
// (surrogate for a quite long and detailed try-catch-block anywhere before)
throw("Invalid arguments for primeGenerator()");
}

View file

@ -0,0 +1,11 @@
// first 20 primes
console.log(primeGenerator(20, true));
// primes between 100 and 150
console.log(primeGenerator([100, 150], true));
// numbers of primes between 7700 and 8000
console.log(primeGenerator([7700, 8000], false));
// the 10,000th prime
console.log(primeGenerator(10000, false));

View file

@ -0,0 +1,7 @@
Array [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 51, 59, 61, 67, 71 ]
Array [ 101, 103, 107, 109, 113, 127, 131, 137, 139, 149 ]
30
104729

View file

@ -1,46 +1,46 @@
/*REXX program finds primes using an extendible prime number generator.*/
parse arg f .; if f=='' then f=20 /*allow specifying # for 1 ──► F.*/
call primes f; do j=1 for f; $=$ @.j; end
say 'first' f 'primes are:' $
/*REXX program calculates and displays primes using an extendible prime number generator*/
parse arg f .; if f=='' then f=20 /*allow specifying number for 1 ──► F.*/
call primes f; do j=1 for f; $=$ @.j; end /*j*/
say 'first' f 'primes are:' $
say
call primes -150; do j=100 to 150; if !.j==0 then iterate; $=$ j; end
say 'the primes between 100 to 150 (inclusive) are:' $
call primes -150; do j=100 to 150; if !.j==0 then iterate; $=$ j; end /*j*/
say 'the primes between 100 to 150 (inclusive) are:' $
say
call primes -8000; do j=7700 to 8000; if !.j==0 then iterate; $=$ j; end
call primes -8000; do j=7700 to 8000; if !.j==0 then iterate; $=$ j; end /*j*/
say 'the number of primes between 7700 and 8000 (inclusive) is:' words($)
say
call primes 10000
say 'the 10000th prime is:' @.10000
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────PRIMES subroutine───────────────────*/
primes: procedure expose !. s. @. $ #; parse arg H . 1 m .,,$; H=abs(H)
if symbol('!.0')=='LIT' then /*1st time here? Initialize stuff*/
do; !.=0; @.=0; s.=0 /*!.x=some prime; @.n=Nth prime.*/
_=2 3 5 7 11 13 17 19 23 /*generate a bunch of low primes.*/
do #=1 for words(_); p=word(_,#); @.#=p; !.p=1; end
#=#-1; !.0=#; s.#=@.#**2 /*set # to be number of primes.*/
end /* [↑] done with building low Ps*/
neg= m<0 /*Neg? Request is for a P value.*/
if neg then if H<=@.# then return /*Have a high enough P already?*/
else nop /*used to match the above THEN. */
else if H<=# then return /*Have a enough primes already ? */
/*─────────────────────────────────────── [↓] gen more P's within range*/
do j=@.#+2 by 2 /*find primes until have H Primes*/
if j//3 ==0 then iterate /*is J divisible by three? */
if right(j,1)==5 then iterate /*is the right-most digit a "5" ?*/
if j//7 ==0 then iterate /*is J divisible by seven? */
if j//11 ==0 then iterate /*is J divisible by eleven? */
if j//13 ==0 then iterate /*is J divisible by thirteen? */
if j//17 ==0 then iterate /*is J divisible by seventeen? */
if j//19 ==0 then iterate /*is J divisible by nineteen? */
/*[↑] above seven lines saves time*/
do k=!.0 while s.k<=j /*divide by the known odd primes.*/
if j//@.k==0 then iterate j /*Is J divisible by P? Not prime.*/
end /*k*/ /* [↑] divide by odd primes √j.*/
#=#+1 /*bump number of primes found. */
@.#=j; s.#=j*j; !.j=1 /*assign to sparse array; prime².*/
if neg then if H<=@.# then leave /*do we have a high enough prime?*/
else nop /*used to match the above THEN. */
else if H<=# then leave /*do we have enough primes yet? */
end /*j*/ /* [↑] keep generating 'til nuff*/
return /*return to invoker with more Ps.*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
primes: procedure expose !. s. @. $ #; parse arg H . 1 m .,,$; H=abs(H)
if symbol('!.0')=='LIT' then /*1st time here? Then initialize stuff*/
do; !.=0; @.=0; s.=0 /*!.x = some prime; @.n = Nth prime. */
_=2 3 5 7 11 13 17 19 23 /*generate a bunch of low primes. */
do #=1 for words(_); p=word(_,#); @.#=p; !.p=1; end
#=#-1; !.0=#; s.#=@.#**2 /*set # to be the number of primes. */
end /* [↑] done with building low primes? */
neg= m<0 /*Negative? Request is for a P value.*/
if neg then if H<=@.# then return /*do we have a high enough P already?*/
else nop /*this is used to match the above THEN.*/
else if H<=# then return /*do we have a enough primes already ? */
/* [↓] gen more primes within range. */
do j=@.#+2 by 2 /*find primes until have H Primes. */
if j//3 ==0 then iterate /*is J divisible by three? */
parse var j '' -1 _; if _==5 then iterate /*is the right-most digit a 5?*/
if j//7 ==0 then iterate /*is J divisible by seven? */
if j//11==0 then iterate /*is J divisible by eleven? */
if j//13==0 then iterate /*is J divisible by thirteen? */
if j//17==0 then iterate /*is J divisible by seventeen? */
if j//19==0 then iterate /*is J divisible by nineteen? */
/*[↑] above five lines saves time. */
do k=!.0 while s.k<=j /*divide by the known odd primes. */
if j//@.k==0 then iterate j /*Is J ÷ by a prime? ¬prime. ___*/
end /*k*/ /* [↑] divide by odd primes up to √ j */
#=#+1 /*bump the number of primes found. */
@.#=j; s.#=j*j; !.j=1 /*assign to sparse array; prime²; P#.*/
if neg then if H<=@.# then leave /*do we have a high enough prime? */
else nop /*used to match the above THEN. */
else if H<=# then leave /*do we have enough primes yet? */
end /*j*/ /* [↑] keep generating until enough. */
return /*return to invoker with more primes. */

View file

@ -2,17 +2,17 @@ $ include "seed7_05.s7i";
const func boolean: isPrime (in integer: number) is func
result
var boolean: result is FALSE;
var boolean: prime is FALSE;
local
var integer: count is 2;
begin
if number = 2 then
result := TRUE;
prime := TRUE;
elsif number > 2 then
while number rem count <> 0 and count * count <= number do
incr(count);
end while;
result := number rem count <> 0;
prime := number rem count <> 0;
end if;
end func;
@ -21,12 +21,12 @@ var integer: primeNum is 0;
const func integer: getPrime is func
result
var integer: prime is 0;
var integer: nextPrime is 0;
begin
repeat
incr(currentPrime);
until isPrime(currentPrime);
prime := currentPrime;
nextPrime := currentPrime;
incr(primeNum);
end func;