Prime String
January 10, 2017
My first version of the program prebuilt the prime string to some large length and simply indexed into that string. That worked, but I was dissatisfied because it required a large amount of storage, and inevitably fails when a too-large n is requested. But it did make a nice way to check results of my finished algorithm, so it wasn’t a total loss.
My second version of the program tried to calculate the lengths of the primes and work out where exactly the index occurred within the sequence of prime numbers, but that didn’t work; more precisely, I never convinced myself that I had found the last bug in the program. The problem is that there are lots of edge cases where the requested index doesn’t point to the beginning of a prime, and there are other edge cases where the next five characters spill across a boundary from one prime length to another, and my code kept getting more and more complicated to handle those edge cases, so eventually I threw away that version.
The third version of the program keeps a sliding window on the string, generating primes as necessary. If the window is too small, it is extended. If the index of the first character in the window is less than the target index, the window slides one character to the right. When the window finally reaches the target index, there are guaranteed to be enough characters to form a result, so the function returns. There are no special edge cases at the beginning of the prime string, or when the number of digits in the current prime is greater than its predecessor, or when the target index points to the middle of a prime, or anything else:
(define (prime-substring n) (let ((ps (primegen))) (let loop ((i 0) (str "")) (cond ((string (ps))))) ((< i n) (loop (+ i 1) (substring str 1 (string-length str)))) (else (substring str 0 5))))))
Here are some examples:
> (prime-substring 50) "03107" > (prime-substring 1000) "98719" > (prime-substring 10000) "02192"
We used the prime generator primegen
from a previous exercise. You can run the program at http://ideone.com/DaU4pX.
In Python. primegen is a lazy prime generator.
Decoupling digit generation from slice selection, in Python.
A Haskell version.
This is Julia 0.5, with its new generator expressions. I didn’t find an unbounded prime generator (one could be written) so I just fake it with a sufficiently large pool of primes, which is readily available. Julia’s iteration protocol is similar to but different from that of Python, ISWIM. In particular, the value of a generator expression does not itself have state.
(Re my Julia above, a nicer way to count the total number of digits in primes below 2017.)
Here’s some JS using the new ES6 generators. This one only starts building up the string once the first required prime is reached, before that it just keep a character count for the primes seen. Uses a simple incremental sieve of Eratosthenes – not the most efficient, but does the job.
package prime.string;
import static java.lang.System.out;
import java.util.Scanner;
public class PrimeString {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
out.print(“Enter the index: “);
int index = keyboard.nextInt();
out.println();
int a = 2;
String b = “”;
while(b.length() < index+5)
{
if(a % 2 != 0 && a % 3 != 0 && a % 5 != 0 && a % 7 != 0 || (a == 2 || a == 3 || a == 5 || a == 7))
{
b += a;
}
a++;
}
System.out.println(b.substring(index,index+5));
}
}