JUnit: PrimeGensTest.java In Python 3, all kinds of lazy sequences are easy to produce with generators ,
Question:
JUnit: PrimeGensTest.java
In Python 3, all kinds of lazy sequences are easy to produce with generators, special functions that yield their results one element at the time and then continue their execution from the exact point where they left off in the previous call, instead of always starting their execution of the function body from the beginning the way ordinary functions do in both Python and Java. The Java language does not offer generators (at least not around the version that this author is familiar with), but the idea of lazy iteration over computationally generated inYinite sequences is still very much worth learning, and Yits snugly into the Iterator class hierarchy of Java Collection Framework.
This lab continues the work from the previous lab by using its methods isPrime and kthPrime as helper methods to produce the subsequence of all prime numbers that satisfy some additional requirements collected on the Wikipedia page listing these special subtypes of prime numbers. Create a new utility wrapper class PrimeGens inside which you write no /ields or methods whatsoever, but three public static nested classes. Each of these classes acts as an in/inite iterator of prime numbers that are not explicitly stored anywhere, but are generated lazily whenever the user code request the next such prime number.
Each of these three classes should deYine the basic methods required by Iterator. The method public boolean hasNext() should always return true, since for our purposes, all these sequences are inYinite. (It is currently unknown whether the twin primes sequence is truly inYinite, but there are enough twin primes for us to not run out during the JUnit tests.) The method public Integer next() generates the next element of that sequence.
First, to help you get started with the required three nested classes, below is a complete model implementation of two such example classes. The Yirst one produces all palindromic prime numbers, and the second produces all composite numbers, that is, those that are not primes. Your three classes will have the same structure as these, but use different logic inside the method next to Yind the next prime number with the required property. (Note also the tactical use of both pre- and post/ix forms of the ++ operator in Composites.)
public static class PalindromicPrimes implements Iterator { private int k = 0; // Current position in the prime sequence public boolean hasNext() { return true; } // Infinite sequence public Integer next() {
while(true) {
int p = Primes.kthPrime(k++); String digits = "" + p;
if(digits.equals(new StringBuilder(digits).reverse().toString())) { return p;
}
}
}
}
public static class Composites implements Iterator { private int curr = 4, k = 2, nextPrime = Primes.kthPrime(2); public boolean hasNext() { return true; }
public Integer next() { if(curr == nextPrime) {
nextPrime = Primes.kthPrime(++k); curr++;
}
return curr++;
}
}
Having carefully studied both classes until you can explain what each line does, the three nested classes that you write inside class PrimeGens for you to write are as follows. You can quickly and easily test your implementations with a simple main method that Yirst creates an instance of the said iterator, and then uses a for-loop to print out the Yirst couple of dozen elements for you to compare to the expected initial sequences given below. Once the Yirst twenty or thereabouts special primes produced by your iterator match the expected sequence, it is nearly certain that the rest will also follow suit, same as even though the race is not always to the swift nor the battle to the strong, that is still the way to bet. (At some point incredible luck becomes indistinguishable from incredible skill, if only to mangle Arthur C. Clarke's famous observation about science and magic.)
public static class TwinPrimes implements Iterator
Generates all twin primes; prime numbers p for which p+2 is also a prime number. This sequence begins 3, 5, 11, 17, 29, 41, 59, 71, 101, 107, 137, 149, 179, 191, 197, 227, 239, 269, 281, 311, ...
public static class SafePrimes implements Iterator
Generates all safe primes that can be expressed in the form 2*p+1 where p is also a prime number. (The smaller prime p that establishes the "safety" of the prime 2*p+1 in certain technical sense is led a "Sophie Germain prime"). This sequence begins 5, 7, 11, 23, 47, 59, 83, 107, 167, 179,
27, 263, 347, 359, 383, 467, 479, 503, 563, 587, 719, 839, 863, ...
public static class StrongPrimes implements Iterator
Generates all strong primes, primes p that are larger than the mathematical average of the previous and next prime numbers around p in the sequence of all prime numbers. This sequence begins 11, 17, 29, 37, 41, 59, 67, 71, 79, 97, 101, 107, 127, 137, 149, 163, 179, 191, 197, 223, 227, 239, 251, ...
TEST CODE:
import org.junit.Test; import java.util.Iterator; import java.util.zip.CRC32; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; public class PrimeGensTest { // Expected prefixes of the infinite sequences of twin primes, safe primes and strong primes. private static final int[] TWIN_PRIMES_PREFIX = { 3, 5, 11, 17, 29, 41, 59, 71, 101, 107, 137, 149, 179, 191, 197, 227, 239, 269, 281, 311 }; private static final int[] SAFE_PRIMES_PREFIX = { 5, 7, 11, 23, 47, 59, 83, 107, 167, 179, 227, 263, 347, 359, 383, 467, 479, 503, 563, 587, 719, 839, 863 }; private static final int[] STRONG_PRIMES_PREFIX = { 11, 17, 29, 37, 41, 59, 67, 71, 79, 97, 101, 107, 127, 137, 149, 163, 179, 191, 197, 223, 227, 239, 251 }; @Test public void testTwinPrimes() { Iterator it = new PrimeGens.TwinPrimes(); int[] result = new int[TWIN_PRIMES_PREFIX.length]; for(int i = 0; i < TWIN_PRIMES_PREFIX.length; i++) { result[i] = it.next(); } assertArrayEquals(TWIN_PRIMES_PREFIX, result); CRC32 check = new CRC32(); it = new PrimeGens.TwinPrimes(); for(int i = 0; i < 3500; i++) { check.update(it.next()); } assertEquals(2941193748L, check.getValue()); } @Test public void testSafePrimes() { Iterator it = new PrimeGens.SafePrimes(); int[] result = new int[SAFE_PRIMES_PREFIX.length]; for(int i = 0; i < SAFE_PRIMES_PREFIX.length; i++) { result[i] = it.next(); } assertArrayEquals(SAFE_PRIMES_PREFIX, result); CRC32 check = new CRC32(); it = new PrimeGens.SafePrimes(); for(int i = 0; i < 3000; i++) { check.update(it.next()); } assertEquals(3874618335L, check.getValue()); } @Test public void testStrongPrimes() { Iterator it = new PrimeGens.StrongPrimes(); int[] result = new int[STRONG_PRIMES_PREFIX.length]; for(int i = 0; i < STRONG_PRIMES_PREFIX.length; i++) { result[i] = it.next(); } assertArrayEquals(STRONG_PRIMES_PREFIX, result); CRC32 check = new CRC32(); it = new PrimeGens.StrongPrimes(); for(int i = 0; i < 15_000; i++) { check.update(it.next()); } assertEquals(494629196L, check.getValue()); } }
A Concise Introduction to Logic
ISBN: 978-1305958098
13th edition
Authors: Patrick J. Hurley, Lori Watson