From b0444c11b07408a4745282bdf703d280f0b14e1d Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Mon, 21 Apr 2025 01:50:35 +0900 Subject: [PATCH 01/14] PrimorialOrder --- .../primes/PrimorialOrder.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/main/java/com/autonomouslogic/primes/PrimorialOrder.java diff --git a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java new file mode 100644 index 0000000..bd6283c --- /dev/null +++ b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java @@ -0,0 +1,46 @@ +package com.autonomouslogic.primes; + +import java.util.Arrays; +import java.util.stream.LongStream; +import lombok.AllArgsConstructor; +import lombok.Value; + +@Value +@AllArgsConstructor +public class PrimorialOrder { + int order; + long primeProduct; + long[] probablePrimeOffsets; + + public LongStream getProbablePrimes() { + return LongStream.iterate(1, i -> i + 1) + .flatMap(k -> Arrays.stream(probablePrimeOffsets).map(i -> k * primeProduct + i)); + } + + public static PrimorialOrder ofOrder(int order) { + var primes = Arrays.stream(PrimeList.PRIMES).limit(order).toArray(); + long product = 1; + for (int prime : primes) { + product *= prime; + } + final var finalProduct = product; + var offsets = LongStream.range(product, 2 * product) + .filter(n -> { + for (int prime : primes) { + if ((n % prime) == 0) { + return false; + } + } + return true; + }) + .map(n -> n - finalProduct) + .toArray(); + return new PrimorialOrder(order, product, offsets); + } + + public static void main(String[] args) { + for (int i = 0; i <= 4; i++) { + System.out.println(PrimorialOrder.ofOrder(i)); + } + } +} From 694a101d49105b16b33bec724aceb8c71c512590 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Mon, 21 Apr 2025 01:59:52 +0900 Subject: [PATCH 02/14] PrimorialOrderTest --- .../primes/PrimorialOrderTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java new file mode 100644 index 0000000..d1e5ea4 --- /dev/null +++ b/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java @@ -0,0 +1,46 @@ +package com.autonomouslogic.primes; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +public class PrimorialOrderTest { + @ParameterizedTest + @MethodSource("orderTests") + void shouldCreateOrders(int order, PrimorialOrder expected) { + assertEquals(expected, PrimorialOrder.ofOrder(order)); + } + + public static Stream orderTests() { + return Stream.of( + Arguments.of(0, new PrimorialOrder(0, 1, new long[] {0})), + Arguments.of(1, new PrimorialOrder(1, 2, new long[] {1})), + Arguments.of(2, new PrimorialOrder(2, 6, new long[] {1, 5})), + Arguments.of(3, new PrimorialOrder(3, 30, new long[] {1, 7, 11, 13, 17, 19, 23, 29}))); + } + + @ParameterizedTest + @MethodSource("probablyPrimesTests") + void shouldReturnProbablePrimes(int order, List expected) { + assertEquals( + expected.toString(), + PrimorialOrder.ofOrder(order) + .getProbablePrimes() + .limit(expected.size()) + .boxed() + .toList() + .toString()); + } + + public static Stream probablyPrimesTests() { + return Stream.of( + Arguments.of(0, List.of(1, 2, 3, 4, 5, 6, 7)), + Arguments.of(1, List.of(3, 5, 7, 9, 11, 13, 15)), + Arguments.of(2, List.of(7, 11, 13, 17)), + Arguments.of(3, List.of(31, 37, 41, 43, 47, 49, 53, 59, 61, 67, 71, 73, 77, 79, 83, 89))); + } +} From 24c2cab4c320ceed14a0a0e5e12e74f3e1679372 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Wed, 23 Apr 2025 10:17:36 +0900 Subject: [PATCH 03/14] More primorials --- .../primes/PrimorialOrder.java | 61 ++++++++++++++++--- .../primes/PrimorialOrderTest.java | 10 +-- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java index bd6283c..c00e4bf 100644 --- a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java +++ b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java @@ -5,18 +5,57 @@ import lombok.AllArgsConstructor; import lombok.Value; +/** + *

+ * An order of priomorial. + * Each order n is the primorial p_n#. + * Each order consists of the order n, the last prime c, the product k, + * and all the coprime offsets iOffsets from k. + *

+ * + *

+ * See Primorial + * and Primality test (Simple methods). + *

+ * + *

+ * The main function in this class summarises the orders with the output: + *

+ * Order 0, c=1, k=1, 1 offsets, 100.0% space
+ * Order 1, c=2, k=2, 1 offsets, 50.0% space
+ * Order 2, c=3, k=6, 2 offsets, 33.3% space
+ * Order 3, c=5, k=30, 8 offsets, 26.7% space
+ * Order 4, c=7, k=210, 48 offsets, 22.9% space
+ * Order 5, c=11, k=2310, 480 offsets, 20.8% space
+ * Order 6, c=13, k=30030, 5760 offsets, 19.2% space
+ * Order 7, c=17, k=510510, 92160 offsets, 18.1% space
+ * Order 8, c=19, k=9699690, 1658880 offsets, 17.1% space
+ * Order 9, c=23, k=223092870, 36495360 offsets, 16.4% space
+ * 
+ *

+ */ @Value @AllArgsConstructor public class PrimorialOrder { - int order; - long primeProduct; - long[] probablePrimeOffsets; + int n; + int c; + long k; + long[] iOffsets; - public LongStream getProbablePrimes() { + /** + * Returns all possible primes associated with this order. + * @return + */ + public LongStream possiblePrimes() { return LongStream.iterate(1, i -> i + 1) - .flatMap(k -> Arrays.stream(probablePrimeOffsets).map(i -> k * primeProduct + i)); + .flatMap(k -> Arrays.stream(iOffsets).map(i -> k * this.k + i)); } + /** + * Returns a specific primorial order. + * @param order + * @return + */ public static PrimorialOrder ofOrder(int order) { var primes = Arrays.stream(PrimeList.PRIMES).limit(order).toArray(); long product = 1; @@ -35,12 +74,18 @@ public static PrimorialOrder ofOrder(int order) { }) .map(n -> n - finalProduct) .toArray(); - return new PrimorialOrder(order, product, offsets); + var c = primes.length == 0 ? 1 : primes[primes.length - 1]; + return new PrimorialOrder(order, c, product, offsets); } public static void main(String[] args) { - for (int i = 0; i <= 4; i++) { - System.out.println(PrimorialOrder.ofOrder(i)); + for (int i = 0; i <= 9; i++) { + var order = PrimorialOrder.ofOrder(i); + var offsetsLen = order.getIOffsets().length; + var space = 100.0 * offsetsLen / order.getK(); + System.out.printf( + "Order %d, c=%d, k=%d, %d offsets, %.1f%% space%n", + order.getN(), order.getC(), order.getK(), offsetsLen, space); } } } diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java index d1e5ea4..d1d451d 100644 --- a/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java +++ b/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java @@ -17,10 +17,10 @@ void shouldCreateOrders(int order, PrimorialOrder expected) { public static Stream orderTests() { return Stream.of( - Arguments.of(0, new PrimorialOrder(0, 1, new long[] {0})), - Arguments.of(1, new PrimorialOrder(1, 2, new long[] {1})), - Arguments.of(2, new PrimorialOrder(2, 6, new long[] {1, 5})), - Arguments.of(3, new PrimorialOrder(3, 30, new long[] {1, 7, 11, 13, 17, 19, 23, 29}))); + Arguments.of(0, new PrimorialOrder(0, 1, 1, new long[] {0})), + Arguments.of(1, new PrimorialOrder(1, 2, 2, new long[] {1})), + Arguments.of(2, new PrimorialOrder(2, 3, 6, new long[] {1, 5})), + Arguments.of(3, new PrimorialOrder(3, 5, 30, new long[] {1, 7, 11, 13, 17, 19, 23, 29}))); } @ParameterizedTest @@ -29,7 +29,7 @@ void shouldReturnProbablePrimes(int order, List expected) { assertEquals( expected.toString(), PrimorialOrder.ofOrder(order) - .getProbablePrimes() + .possiblePrimes() .limit(expected.size()) .boxed() .toList() From 196c85f1d2d08a816b712c6b46ce0340e695fd9c Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Wed, 23 Apr 2025 10:48:01 +0900 Subject: [PATCH 04/14] More primorial --- .../primes/PrimorialOrder.java | 65 ++++++++++++++++--- .../primes/PrimorialOrderTest.java | 53 ++++++++++++++- 2 files changed, 107 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java index c00e4bf..268cfb8 100644 --- a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java +++ b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java @@ -1,6 +1,7 @@ package com.autonomouslogic.primes; import java.util.Arrays; +import java.util.stream.IntStream; import java.util.stream.LongStream; import lombok.AllArgsConstructor; import lombok.Value; @@ -8,7 +9,7 @@ /** *

* An order of priomorial. - * Each order n is the primorial p_n#. + * Each order n is the primorial p_n# = c#. * Each order consists of the order n, the last prime c, the product k, * and all the coprime offsets iOffsets from k. *

@@ -44,6 +45,12 @@ public class PrimorialOrder { /** * Returns all possible primes associated with this order. + * Each number returned is in the form k + i for each i. + * For instance, order 1 will return all odd numbers. + * Order 2 will first return 3 and 5, then 7 and 9, and so on. + * Order 3 will first return 31, 37, 41, 43, 47, 49, 53, 59, then 61, 67, 71, 73, 77, 79, 83, 89, and so on. + * Each order will return a higher start number, but the stream will contain less and less numbers. + * This can be used when searching for prime numbers. * @return */ public LongStream possiblePrimes() { @@ -51,31 +58,73 @@ public LongStream possiblePrimes() { .flatMap(k -> Arrays.stream(iOffsets).map(i -> k * this.k + i)); } + /** + * Returns the primorial p_n# + * @param n + * @return + */ + public static long primorialOfOrder(int n) { + return Arrays.stream(PrimeList.PRIMES).limit(n).asLongStream().reduce(1, (left, right) -> left * right); + } + /** * Returns a specific primorial order. - * @param order + * @param n * @return */ - public static PrimorialOrder ofOrder(int order) { - var primes = Arrays.stream(PrimeList.PRIMES).limit(order).toArray(); + public static PrimorialOrder ofOrder(int n) { + var primes = Arrays.stream(PrimeList.PRIMES).limit(n).toArray(); long product = 1; for (int prime : primes) { product *= prime; } final var finalProduct = product; var offsets = LongStream.range(product, 2 * product) - .filter(n -> { + .filter(num -> { for (int prime : primes) { - if ((n % prime) == 0) { + if ((num % prime) == 0) { return false; } } return true; }) - .map(n -> n - finalProduct) + .map(num -> num - finalProduct) .toArray(); var c = primes.length == 0 ? 1 : primes[primes.length - 1]; - return new PrimorialOrder(order, c, product, offsets); + return new PrimorialOrder(n, c, product, offsets); + } + + /** + * @see #allPossiblePrimes(long) + * @return + */ + public static LongStream allPossiblePrimes() { + return allPossiblePrimes(2); + } + + /** + * Returns all the possible primes from each primorial order in sequence, starting with the supplied number + * @param from the number to start from, must be at least 2 + * @return + */ + public static LongStream allPossiblePrimes(long from) { + if (from < 2) { + throw new IllegalArgumentException("from must be at least 2"); + } + return IntStream.rangeClosed(1, 8) + .mapToObj(PrimorialOrder::ofOrder) + .filter(o -> primorialOfOrder(o.getN() + 1) >= from) + .flatMapToLong(order -> { + if (order.getK() == 8) { + return order.possiblePrimes(); + } + var nextK = primorialOfOrder(order.getN() + 1); + var stream = order.possiblePrimes().takeWhile(num -> num < nextK); + if (order.getK() < from) { + stream = stream.filter(n -> n >= from); + } + return stream; + }); } public static void main(String[] args) { diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java index d1d451d..49386d6 100644 --- a/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java +++ b/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java @@ -3,7 +3,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; +import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.swing.*; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -24,8 +27,8 @@ public static Stream orderTests() { } @ParameterizedTest - @MethodSource("probablyPrimesTests") - void shouldReturnProbablePrimes(int order, List expected) { + @MethodSource("possiblePrimesTests") + void shouldReturnPossiblePrimes(int order, List expected) { assertEquals( expected.toString(), PrimorialOrder.ofOrder(order) @@ -36,11 +39,55 @@ void shouldReturnProbablePrimes(int order, List expected) { .toString()); } - public static Stream probablyPrimesTests() { + public static Stream possiblePrimesTests() { return Stream.of( Arguments.of(0, List.of(1, 2, 3, 4, 5, 6, 7)), Arguments.of(1, List.of(3, 5, 7, 9, 11, 13, 15)), Arguments.of(2, List.of(7, 11, 13, 17)), Arguments.of(3, List.of(31, 37, 41, 43, 47, 49, 53, 59, 61, 67, 71, 73, 77, 79, 83, 89))); } + + @Test + void shouldReturnAllPossiblePrimes() { + var expected = Stream.of( + PrimorialOrder.ofOrder(1).possiblePrimes().takeWhile(n -> n < 6), + PrimorialOrder.ofOrder(2).possiblePrimes().takeWhile(n -> n < 30), + PrimorialOrder.ofOrder(3).possiblePrimes().takeWhile(n -> n < 200)) + .flatMapToLong(s -> s) + .mapToObj(String::valueOf) + .collect(Collectors.joining("\n")); + var actual = PrimorialOrder.allPossiblePrimes() + .takeWhile(n -> n <= 200) + .mapToObj(String::valueOf) + .collect(Collectors.joining("\n")); + assertEquals(expected, actual); + } + + @Test + void shouldReturnAllPossiblePrimesFromOffset() { + var expected = Stream.of( + PrimorialOrder.ofOrder(2) + .possiblePrimes() + .filter(n -> n >= 15) + .takeWhile(n -> n < 30), + PrimorialOrder.ofOrder(3).possiblePrimes().takeWhile(n -> n < 200)) + .flatMapToLong(s -> s) + .mapToObj(String::valueOf) + .collect(Collectors.joining("\n")); + var actual = PrimorialOrder.allPossiblePrimes(15) + .takeWhile(n -> n <= 200) + .mapToObj(String::valueOf) + .collect(Collectors.joining("\n")); + assertEquals(expected, actual); + } + + @Test + void shouldCalculatePrimorialOfOrder() { + assertEquals(1, PrimorialOrder.primorialOfOrder(0)); + assertEquals(2, PrimorialOrder.primorialOfOrder(1)); + assertEquals(6, PrimorialOrder.primorialOfOrder(2)); + assertEquals(30, PrimorialOrder.primorialOfOrder(3)); + assertEquals(210, PrimorialOrder.primorialOfOrder(4)); + assertEquals(2310, PrimorialOrder.primorialOfOrder(5)); + } } From 2a9a015ce9927cdf3a69a7a8155ffac2900ec1e3 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Wed, 23 Apr 2025 10:52:53 +0900 Subject: [PATCH 05/14] Comments --- src/main/java/com/autonomouslogic/primes/PrimorialOrder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java index 268cfb8..b39f208 100644 --- a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java +++ b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java @@ -45,7 +45,7 @@ public class PrimorialOrder { /** * Returns all possible primes associated with this order. - * Each number returned is in the form k + i for each i. + * Each number returned is in the form n * k + i for each possible integer n and each i. * For instance, order 1 will return all odd numbers. * Order 2 will first return 3 and 5, then 7 and 9, and so on. * Order 3 will first return 31, 37, 41, 43, 47, 49, 53, 59, then 61, 67, 71, 73, 77, 79, 83, 89, and so on. @@ -103,7 +103,7 @@ public static LongStream allPossiblePrimes() { } /** - * Returns all the possible primes from each primorial order in sequence, starting with the supplied number + * Returns all the possible primes from each primorial order in sequence, starting from the supplied number * @param from the number to start from, must be at least 2 * @return */ From f5c1a922558b62d55ef6fe70136640aab6f0b652 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Wed, 23 Apr 2025 10:54:33 +0900 Subject: [PATCH 06/14] Spelling --- src/main/java/com/autonomouslogic/primes/PrimorialOrder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java index b39f208..d022ec7 100644 --- a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java +++ b/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java @@ -8,7 +8,7 @@ /** *

- * An order of priomorial. + * An order of primorial. * Each order n is the primorial p_n# = c#. * Each order consists of the order n, the last prime c, the product k, * and all the coprime offsets iOffsets from k. From 8ca6ac456c72144404f561aa04ac2a96d93c996d Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Wed, 23 Apr 2025 23:54:25 +0900 Subject: [PATCH 07/14] Renamed PrimorialOrder to Primorial --- .../{PrimorialOrder.java => Primorial.java} | 10 ++--- ...orialOrderTest.java => PrimorialTest.java} | 43 +++++++++---------- 2 files changed, 26 insertions(+), 27 deletions(-) rename src/main/java/com/autonomouslogic/primes/{PrimorialOrder.java => Primorial.java} (95%) rename src/test/java/com/autonomouslogic/primes/{PrimorialOrderTest.java => PrimorialTest.java} (59%) diff --git a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java b/src/main/java/com/autonomouslogic/primes/Primorial.java similarity index 95% rename from src/main/java/com/autonomouslogic/primes/PrimorialOrder.java rename to src/main/java/com/autonomouslogic/primes/Primorial.java index d022ec7..0e40c78 100644 --- a/src/main/java/com/autonomouslogic/primes/PrimorialOrder.java +++ b/src/main/java/com/autonomouslogic/primes/Primorial.java @@ -37,7 +37,7 @@ */ @Value @AllArgsConstructor -public class PrimorialOrder { +public class Primorial { int n; int c; long k; @@ -72,7 +72,7 @@ public static long primorialOfOrder(int n) { * @param n * @return */ - public static PrimorialOrder ofOrder(int n) { + public static Primorial ofOrder(int n) { var primes = Arrays.stream(PrimeList.PRIMES).limit(n).toArray(); long product = 1; for (int prime : primes) { @@ -91,7 +91,7 @@ public static PrimorialOrder ofOrder(int n) { .map(num -> num - finalProduct) .toArray(); var c = primes.length == 0 ? 1 : primes[primes.length - 1]; - return new PrimorialOrder(n, c, product, offsets); + return new Primorial(n, c, product, offsets); } /** @@ -112,7 +112,7 @@ public static LongStream allPossiblePrimes(long from) { throw new IllegalArgumentException("from must be at least 2"); } return IntStream.rangeClosed(1, 8) - .mapToObj(PrimorialOrder::ofOrder) + .mapToObj(Primorial::ofOrder) .filter(o -> primorialOfOrder(o.getN() + 1) >= from) .flatMapToLong(order -> { if (order.getK() == 8) { @@ -129,7 +129,7 @@ public static LongStream allPossiblePrimes(long from) { public static void main(String[] args) { for (int i = 0; i <= 9; i++) { - var order = PrimorialOrder.ofOrder(i); + var order = Primorial.ofOrder(i); var offsetsLen = order.getIOffsets().length; var space = 100.0 * offsetsLen / order.getK(); System.out.printf( diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialTest.java similarity index 59% rename from src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java rename to src/test/java/com/autonomouslogic/primes/PrimorialTest.java index 49386d6..239c587 100644 --- a/src/test/java/com/autonomouslogic/primes/PrimorialOrderTest.java +++ b/src/test/java/com/autonomouslogic/primes/PrimorialTest.java @@ -5,25 +5,24 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.swing.*; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -public class PrimorialOrderTest { +public class PrimorialTest { @ParameterizedTest @MethodSource("orderTests") - void shouldCreateOrders(int order, PrimorialOrder expected) { - assertEquals(expected, PrimorialOrder.ofOrder(order)); + void shouldCreateOrders(int order, Primorial expected) { + assertEquals(expected, Primorial.ofOrder(order)); } public static Stream orderTests() { return Stream.of( - Arguments.of(0, new PrimorialOrder(0, 1, 1, new long[] {0})), - Arguments.of(1, new PrimorialOrder(1, 2, 2, new long[] {1})), - Arguments.of(2, new PrimorialOrder(2, 3, 6, new long[] {1, 5})), - Arguments.of(3, new PrimorialOrder(3, 5, 30, new long[] {1, 7, 11, 13, 17, 19, 23, 29}))); + Arguments.of(0, new Primorial(0, 1, 1, new long[] {0})), + Arguments.of(1, new Primorial(1, 2, 2, new long[] {1})), + Arguments.of(2, new Primorial(2, 3, 6, new long[] {1, 5})), + Arguments.of(3, new Primorial(3, 5, 30, new long[] {1, 7, 11, 13, 17, 19, 23, 29}))); } @ParameterizedTest @@ -31,7 +30,7 @@ public static Stream orderTests() { void shouldReturnPossiblePrimes(int order, List expected) { assertEquals( expected.toString(), - PrimorialOrder.ofOrder(order) + Primorial.ofOrder(order) .possiblePrimes() .limit(expected.size()) .boxed() @@ -50,13 +49,13 @@ public static Stream possiblePrimesTests() { @Test void shouldReturnAllPossiblePrimes() { var expected = Stream.of( - PrimorialOrder.ofOrder(1).possiblePrimes().takeWhile(n -> n < 6), - PrimorialOrder.ofOrder(2).possiblePrimes().takeWhile(n -> n < 30), - PrimorialOrder.ofOrder(3).possiblePrimes().takeWhile(n -> n < 200)) + Primorial.ofOrder(1).possiblePrimes().takeWhile(n -> n < 6), + Primorial.ofOrder(2).possiblePrimes().takeWhile(n -> n < 30), + Primorial.ofOrder(3).possiblePrimes().takeWhile(n -> n < 200)) .flatMapToLong(s -> s) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); - var actual = PrimorialOrder.allPossiblePrimes() + var actual = Primorial.allPossiblePrimes() .takeWhile(n -> n <= 200) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); @@ -66,15 +65,15 @@ void shouldReturnAllPossiblePrimes() { @Test void shouldReturnAllPossiblePrimesFromOffset() { var expected = Stream.of( - PrimorialOrder.ofOrder(2) + Primorial.ofOrder(2) .possiblePrimes() .filter(n -> n >= 15) .takeWhile(n -> n < 30), - PrimorialOrder.ofOrder(3).possiblePrimes().takeWhile(n -> n < 200)) + Primorial.ofOrder(3).possiblePrimes().takeWhile(n -> n < 200)) .flatMapToLong(s -> s) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); - var actual = PrimorialOrder.allPossiblePrimes(15) + var actual = Primorial.allPossiblePrimes(15) .takeWhile(n -> n <= 200) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); @@ -83,11 +82,11 @@ void shouldReturnAllPossiblePrimesFromOffset() { @Test void shouldCalculatePrimorialOfOrder() { - assertEquals(1, PrimorialOrder.primorialOfOrder(0)); - assertEquals(2, PrimorialOrder.primorialOfOrder(1)); - assertEquals(6, PrimorialOrder.primorialOfOrder(2)); - assertEquals(30, PrimorialOrder.primorialOfOrder(3)); - assertEquals(210, PrimorialOrder.primorialOfOrder(4)); - assertEquals(2310, PrimorialOrder.primorialOfOrder(5)); + assertEquals(1, Primorial.primorialOfOrder(0)); + assertEquals(2, Primorial.primorialOfOrder(1)); + assertEquals(6, Primorial.primorialOfOrder(2)); + assertEquals(30, Primorial.primorialOfOrder(3)); + assertEquals(210, Primorial.primorialOfOrder(4)); + assertEquals(2310, Primorial.primorialOfOrder(5)); } } From 02da8df394e7df6ee1aea514993e02b832ca83a6 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Thu, 24 Apr 2025 00:43:15 +0900 Subject: [PATCH 08/14] More refactor --- .../com/autonomouslogic/primes/Primorial.java | 140 --------------- .../autonomouslogic/primes/Primorials.java | 164 ++++++++++++++++++ ...PrimorialTest.java => PrimorialsTest.java} | 42 ++--- 3 files changed, 185 insertions(+), 161 deletions(-) delete mode 100644 src/main/java/com/autonomouslogic/primes/Primorial.java create mode 100644 src/main/java/com/autonomouslogic/primes/Primorials.java rename src/test/java/com/autonomouslogic/primes/{PrimorialTest.java => PrimorialsTest.java} (60%) diff --git a/src/main/java/com/autonomouslogic/primes/Primorial.java b/src/main/java/com/autonomouslogic/primes/Primorial.java deleted file mode 100644 index 0e40c78..0000000 --- a/src/main/java/com/autonomouslogic/primes/Primorial.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.autonomouslogic.primes; - -import java.util.Arrays; -import java.util.stream.IntStream; -import java.util.stream.LongStream; -import lombok.AllArgsConstructor; -import lombok.Value; - -/** - *

- * An order of primorial. - * Each order n is the primorial p_n# = c#. - * Each order consists of the order n, the last prime c, the product k, - * and all the coprime offsets iOffsets from k. - *

- * - *

- * See Primorial - * and Primality test (Simple methods). - *

- * - *

- * The main function in this class summarises the orders with the output: - *

- * Order 0, c=1, k=1, 1 offsets, 100.0% space
- * Order 1, c=2, k=2, 1 offsets, 50.0% space
- * Order 2, c=3, k=6, 2 offsets, 33.3% space
- * Order 3, c=5, k=30, 8 offsets, 26.7% space
- * Order 4, c=7, k=210, 48 offsets, 22.9% space
- * Order 5, c=11, k=2310, 480 offsets, 20.8% space
- * Order 6, c=13, k=30030, 5760 offsets, 19.2% space
- * Order 7, c=17, k=510510, 92160 offsets, 18.1% space
- * Order 8, c=19, k=9699690, 1658880 offsets, 17.1% space
- * Order 9, c=23, k=223092870, 36495360 offsets, 16.4% space
- * 
- *

- */ -@Value -@AllArgsConstructor -public class Primorial { - int n; - int c; - long k; - long[] iOffsets; - - /** - * Returns all possible primes associated with this order. - * Each number returned is in the form n * k + i for each possible integer n and each i. - * For instance, order 1 will return all odd numbers. - * Order 2 will first return 3 and 5, then 7 and 9, and so on. - * Order 3 will first return 31, 37, 41, 43, 47, 49, 53, 59, then 61, 67, 71, 73, 77, 79, 83, 89, and so on. - * Each order will return a higher start number, but the stream will contain less and less numbers. - * This can be used when searching for prime numbers. - * @return - */ - public LongStream possiblePrimes() { - return LongStream.iterate(1, i -> i + 1) - .flatMap(k -> Arrays.stream(iOffsets).map(i -> k * this.k + i)); - } - - /** - * Returns the primorial p_n# - * @param n - * @return - */ - public static long primorialOfOrder(int n) { - return Arrays.stream(PrimeList.PRIMES).limit(n).asLongStream().reduce(1, (left, right) -> left * right); - } - - /** - * Returns a specific primorial order. - * @param n - * @return - */ - public static Primorial ofOrder(int n) { - var primes = Arrays.stream(PrimeList.PRIMES).limit(n).toArray(); - long product = 1; - for (int prime : primes) { - product *= prime; - } - final var finalProduct = product; - var offsets = LongStream.range(product, 2 * product) - .filter(num -> { - for (int prime : primes) { - if ((num % prime) == 0) { - return false; - } - } - return true; - }) - .map(num -> num - finalProduct) - .toArray(); - var c = primes.length == 0 ? 1 : primes[primes.length - 1]; - return new Primorial(n, c, product, offsets); - } - - /** - * @see #allPossiblePrimes(long) - * @return - */ - public static LongStream allPossiblePrimes() { - return allPossiblePrimes(2); - } - - /** - * Returns all the possible primes from each primorial order in sequence, starting from the supplied number - * @param from the number to start from, must be at least 2 - * @return - */ - public static LongStream allPossiblePrimes(long from) { - if (from < 2) { - throw new IllegalArgumentException("from must be at least 2"); - } - return IntStream.rangeClosed(1, 8) - .mapToObj(Primorial::ofOrder) - .filter(o -> primorialOfOrder(o.getN() + 1) >= from) - .flatMapToLong(order -> { - if (order.getK() == 8) { - return order.possiblePrimes(); - } - var nextK = primorialOfOrder(order.getN() + 1); - var stream = order.possiblePrimes().takeWhile(num -> num < nextK); - if (order.getK() < from) { - stream = stream.filter(n -> n >= from); - } - return stream; - }); - } - - public static void main(String[] args) { - for (int i = 0; i <= 9; i++) { - var order = Primorial.ofOrder(i); - var offsetsLen = order.getIOffsets().length; - var space = 100.0 * offsetsLen / order.getK(); - System.out.printf( - "Order %d, c=%d, k=%d, %d offsets, %.1f%% space%n", - order.getN(), order.getC(), order.getK(), offsetsLen, space); - } - } -} diff --git a/src/main/java/com/autonomouslogic/primes/Primorials.java b/src/main/java/com/autonomouslogic/primes/Primorials.java new file mode 100644 index 0000000..d043b0a --- /dev/null +++ b/src/main/java/com/autonomouslogic/primes/Primorials.java @@ -0,0 +1,164 @@ +package com.autonomouslogic.primes; + +import java.util.Arrays; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Value; + +/** + *

+ * Functions for working with primorials. + * Each order n represents the primorial p_n# = c#, which is the sum of all primes between 2 and c. + * Each order consists of the order n, the last prime c, the product, + * and all the coprime offsets from product. + *

+ * + *

+ * See Primorial + * and Primality test (Simple methods). + *

+ * + *

+ * The main function in this class summarises the orders with the output: + *

+ * Order 0: c=1, k=1, 1 offsets, 100.0% space
+ * Order 1: c=2, k=2, 1 offsets, 50.0% space
+ * Order 2: c=3, k=6, 2 offsets, 33.3% space
+ * Order 3: c=5, k=30, 8 offsets, 26.7% space
+ * Order 4: c=7, k=210, 48 offsets, 22.9% space
+ * Order 5: c=11, k=2310, 480 offsets, 20.8% space
+ * Order 6: c=13, k=30030, 5760 offsets, 19.2% space
+ * Order 7: c=17, k=510510, 92160 offsets, 18.1% space
+ * Order 8: c=19, k=9699690, 1658880 offsets, 17.1% space
+ * Order 9: c=23, k=223092870, 36495360 offsets, 16.4% space
+ * 
+ *

+ */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class Primorials { + @Value + @AllArgsConstructor(access = AccessLevel.PROTECTED) + public static class Order { + /** + * The order of the primorial. + */ + int n; + + /** + * The last prime of the product. + */ + int c; + + /** + * The product of the primorial. + */ + long product; + + /** + * The coprime offsets which when added to multiples of the product are not divisible by any of the primes + * below c. + */ + long[] coprimeOffsets; + + /** + * Returns all possible primes associated with this primorial order. + * Each number returned is in the form product * k + i, where k is an incrementing + * positive integer and i is each possible coprime offset. + * For instance, order 1 will return all odd numbers. + * Order 2 will first return 3 and 5, then 7 and 9, and so on. + * Order 3 will first return 31, 37, 41, 43, 47, 49, 53, 59, then 61, 67, 71, 73, 77, 79, 83, 89, and so on. + * Each order will return a higher start number, but the stream will contain fewer and fewer numbers. + * This can be used when searching for prime numbers. + * + * @return + */ + public LongStream possiblePrimes() { + return LongStream.iterate(1, i -> i + 1) + .flatMap(k -> Arrays.stream(coprimeOffsets).map(i -> k * this.product + i)); + } + } + + /** + * Returns the primorial p_n# + * @param n + * @return + */ + public static long ofOrder(int n) { + return Arrays.stream(PrimeList.PRIMES).limit(n).asLongStream().reduce(1, (left, right) -> left * right); + } + + /** + * Returns a primorial order with all the coprime offsets calculated. + * @param n + * @return + */ + public static Primorials.Order ofOrderWithCoprimes(int n) { + var primes = Arrays.stream(PrimeList.PRIMES).limit(n).toArray(); + long product = 1; + for (int prime : primes) { + product *= prime; + } + final var finalProduct = product; + var offsets = LongStream.range(product, 2 * product) + .filter(num -> { + for (int prime : primes) { + if ((num % prime) == 0) { + return false; + } + } + return true; + }) + .map(num -> num - finalProduct) + .toArray(); + var c = primes.length == 0 ? 1 : primes[primes.length - 1]; + return new Primorials.Order(n, c, product, offsets); + } + + /** + * @see #allPossiblePrimes(long) + * @return + */ + public static LongStream allPossiblePrimes() { + return allPossiblePrimes(2); + } + + /** + * Returns all the possible primes from each primorial order in sequence, starting from the supplied number. + * The sequence will gradually contain fewer and fewer numbers as the orders are able to advance. + * @param from the number to start from, must be at least 2 + * @return + */ + public static LongStream allPossiblePrimes(long from) { + if (from < 2) { + throw new IllegalArgumentException("from must be at least 2"); + } + return IntStream.rangeClosed(1, 8) + .mapToObj(Primorials::ofOrderWithCoprimes) + .filter(o -> ofOrder(o.getN() + 1) >= from) + .flatMapToLong(order -> { + if (order.getProduct() == 8) { + return order.possiblePrimes(); + } + var nextK = ofOrder(order.getN() + 1); + var stream = order.possiblePrimes().takeWhile(num -> num < nextK); + if (order.getProduct() < from) { + stream = stream.filter(n -> n >= from); + } + return stream; + }); + } + + public static void main(String[] args) { + for (int i = 0; i <= 9; i++) { + var order = Primorials.ofOrderWithCoprimes(i); + var offsetsLen = order.getCoprimeOffsets().length; + var space = 100.0 * offsetsLen / order.getProduct(); + System.out.printf( + "Order %d, c=%d, k=%d, %d offsets, %.1f%% space%n", + order.getN(), order.getC(), order.getProduct(), offsetsLen, space); + } + } +} diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java similarity index 60% rename from src/test/java/com/autonomouslogic/primes/PrimorialTest.java rename to src/test/java/com/autonomouslogic/primes/PrimorialsTest.java index 239c587..e9347bd 100644 --- a/src/test/java/com/autonomouslogic/primes/PrimorialTest.java +++ b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java @@ -10,19 +10,19 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -public class PrimorialTest { +public class PrimorialsTest { @ParameterizedTest @MethodSource("orderTests") - void shouldCreateOrders(int order, Primorial expected) { - assertEquals(expected, Primorial.ofOrder(order)); + void shouldCreateOrders(int order, Primorials.Order expected) { + assertEquals(expected, Primorials.ofOrderWithCoprimes(order)); } public static Stream orderTests() { return Stream.of( - Arguments.of(0, new Primorial(0, 1, 1, new long[] {0})), - Arguments.of(1, new Primorial(1, 2, 2, new long[] {1})), - Arguments.of(2, new Primorial(2, 3, 6, new long[] {1, 5})), - Arguments.of(3, new Primorial(3, 5, 30, new long[] {1, 7, 11, 13, 17, 19, 23, 29}))); + Arguments.of(0, new Primorials.Order(0, 1, 1, new long[] {0})), + Arguments.of(1, new Primorials.Order(1, 2, 2, new long[] {1})), + Arguments.of(2, new Primorials.Order(2, 3, 6, new long[] {1, 5})), + Arguments.of(3, new Primorials.Order(3, 5, 30, new long[] {1, 7, 11, 13, 17, 19, 23, 29}))); } @ParameterizedTest @@ -30,7 +30,7 @@ public static Stream orderTests() { void shouldReturnPossiblePrimes(int order, List expected) { assertEquals( expected.toString(), - Primorial.ofOrder(order) + Primorials.ofOrderWithCoprimes(order) .possiblePrimes() .limit(expected.size()) .boxed() @@ -49,13 +49,13 @@ public static Stream possiblePrimesTests() { @Test void shouldReturnAllPossiblePrimes() { var expected = Stream.of( - Primorial.ofOrder(1).possiblePrimes().takeWhile(n -> n < 6), - Primorial.ofOrder(2).possiblePrimes().takeWhile(n -> n < 30), - Primorial.ofOrder(3).possiblePrimes().takeWhile(n -> n < 200)) + Primorials.ofOrderWithCoprimes(1).possiblePrimes().takeWhile(n -> n < 6), + Primorials.ofOrderWithCoprimes(2).possiblePrimes().takeWhile(n -> n < 30), + Primorials.ofOrderWithCoprimes(3).possiblePrimes().takeWhile(n -> n < 200)) .flatMapToLong(s -> s) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); - var actual = Primorial.allPossiblePrimes() + var actual = Primorials.allPossiblePrimes() .takeWhile(n -> n <= 200) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); @@ -65,15 +65,15 @@ void shouldReturnAllPossiblePrimes() { @Test void shouldReturnAllPossiblePrimesFromOffset() { var expected = Stream.of( - Primorial.ofOrder(2) + Primorials.ofOrderWithCoprimes(2) .possiblePrimes() .filter(n -> n >= 15) .takeWhile(n -> n < 30), - Primorial.ofOrder(3).possiblePrimes().takeWhile(n -> n < 200)) + Primorials.ofOrderWithCoprimes(3).possiblePrimes().takeWhile(n -> n < 200)) .flatMapToLong(s -> s) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); - var actual = Primorial.allPossiblePrimes(15) + var actual = Primorials.allPossiblePrimes(15) .takeWhile(n -> n <= 200) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); @@ -82,11 +82,11 @@ void shouldReturnAllPossiblePrimesFromOffset() { @Test void shouldCalculatePrimorialOfOrder() { - assertEquals(1, Primorial.primorialOfOrder(0)); - assertEquals(2, Primorial.primorialOfOrder(1)); - assertEquals(6, Primorial.primorialOfOrder(2)); - assertEquals(30, Primorial.primorialOfOrder(3)); - assertEquals(210, Primorial.primorialOfOrder(4)); - assertEquals(2310, Primorial.primorialOfOrder(5)); + assertEquals(1, Primorials.ofOrder(0)); + assertEquals(2, Primorials.ofOrder(1)); + assertEquals(6, Primorials.ofOrder(2)); + assertEquals(30, Primorials.ofOrder(3)); + assertEquals(210, Primorials.ofOrder(4)); + assertEquals(2310, Primorials.ofOrder(5)); } } From bfd006ed6118cbbd9519de3e7b7899e99024a844 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Thu, 24 Apr 2025 00:45:44 +0900 Subject: [PATCH 09/14] Fix --- src/main/java/com/autonomouslogic/primes/Primorials.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/autonomouslogic/primes/Primorials.java b/src/main/java/com/autonomouslogic/primes/Primorials.java index d043b0a..4c47bb3 100644 --- a/src/main/java/com/autonomouslogic/primes/Primorials.java +++ b/src/main/java/com/autonomouslogic/primes/Primorials.java @@ -59,7 +59,7 @@ public static class Order { /** * The coprime offsets which when added to multiples of the product are not divisible by any of the primes - * below c. + * less than or equal to c. */ long[] coprimeOffsets; @@ -157,7 +157,7 @@ public static void main(String[] args) { var offsetsLen = order.getCoprimeOffsets().length; var space = 100.0 * offsetsLen / order.getProduct(); System.out.printf( - "Order %d, c=%d, k=%d, %d offsets, %.1f%% space%n", + "Order %d: c=%d, product=%d, %d coprime offsets, %.1f%% space%n", order.getN(), order.getC(), order.getProduct(), offsetsLen, space); } } From 57fa858e4e82fcda18972941c1a9c6441a5b5e04 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Thu, 24 Apr 2025 00:46:33 +0900 Subject: [PATCH 10/14] Docs --- .../autonomouslogic/primes/Primorials.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/autonomouslogic/primes/Primorials.java b/src/main/java/com/autonomouslogic/primes/Primorials.java index 4c47bb3..9984268 100644 --- a/src/main/java/com/autonomouslogic/primes/Primorials.java +++ b/src/main/java/com/autonomouslogic/primes/Primorials.java @@ -24,16 +24,16 @@ *

* The main function in this class summarises the orders with the output: *

- * Order 0: c=1, k=1, 1 offsets, 100.0% space
- * Order 1: c=2, k=2, 1 offsets, 50.0% space
- * Order 2: c=3, k=6, 2 offsets, 33.3% space
- * Order 3: c=5, k=30, 8 offsets, 26.7% space
- * Order 4: c=7, k=210, 48 offsets, 22.9% space
- * Order 5: c=11, k=2310, 480 offsets, 20.8% space
- * Order 6: c=13, k=30030, 5760 offsets, 19.2% space
- * Order 7: c=17, k=510510, 92160 offsets, 18.1% space
- * Order 8: c=19, k=9699690, 1658880 offsets, 17.1% space
- * Order 9: c=23, k=223092870, 36495360 offsets, 16.4% space
+ * Order 0: c=1, product=1, 1 coprime offsets, 100.0% space
+ * Order 1: c=2, product=2, 1 coprime offsets, 50.0% space
+ * Order 2: c=3, product=6, 2 coprime offsets, 33.3% space
+ * Order 3: c=5, product=30, 8 coprime offsets, 26.7% space
+ * Order 4: c=7, product=210, 48 coprime offsets, 22.9% space
+ * Order 5: c=11, product=2310, 480 coprime offsets, 20.8% space
+ * Order 6: c=13, product=30030, 5760 coprime offsets, 19.2% space
+ * Order 7: c=17, product=510510, 92160 coprime offsets, 18.1% space
+ * Order 8: c=19, product=9699690, 1658880 coprime offsets, 17.1% space
+ * Order 9: c=23, product=223092870, 36495360 coprime offsets, 16.4% space
  * 
*

*/ From a03695692708d808f692676fa4916150d761bfa6 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Thu, 24 Apr 2025 01:03:37 +0900 Subject: [PATCH 11/14] Fixed up tests --- .../primes/PrimorialsTest.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java index e9347bd..f13aec8 100644 --- a/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java +++ b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java @@ -13,7 +13,7 @@ public class PrimorialsTest { @ParameterizedTest @MethodSource("orderTests") - void shouldCreateOrders(int order, Primorials.Order expected) { + void shouldCreateOrdersWithCoprimeOffsets(int order, Primorials.Order expected) { assertEquals(expected, Primorials.ofOrderWithCoprimes(order)); } @@ -80,13 +80,19 @@ void shouldReturnAllPossiblePrimesFromOffset() { assertEquals(expected, actual); } - @Test - void shouldCalculatePrimorialOfOrder() { - assertEquals(1, Primorials.ofOrder(0)); - assertEquals(2, Primorials.ofOrder(1)); - assertEquals(6, Primorials.ofOrder(2)); - assertEquals(30, Primorials.ofOrder(3)); - assertEquals(210, Primorials.ofOrder(4)); - assertEquals(2310, Primorials.ofOrder(5)); + @ParameterizedTest + @MethodSource("primorialTests") + void shouldCalculatePrimorialOfOrder(int order, int expected) { + assertEquals(expected, Primorials.ofOrder(order)); + } + + public static Stream primorialTests() { + return Stream.of( + Arguments.of(0, 1), + Arguments.of(1, 2), + Arguments.of(2, 6), + Arguments.of(3, 30), + Arguments.of(4, 210), + Arguments.of(5, 2310)); } } From 656bc92e408d1fa2f7fd0ce5be0e1841d40f6eb6 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Thu, 24 Apr 2025 01:21:06 +0900 Subject: [PATCH 12/14] Fixes and tried integrating possible primes into TrialDivision --- .../autonomouslogic/primes/Primorials.java | 7 +++++- .../autonomouslogic/primes/TrialDivision.java | 24 ++++++++++++++++--- .../primes/PrimorialsTest.java | 2 ++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/autonomouslogic/primes/Primorials.java b/src/main/java/com/autonomouslogic/primes/Primorials.java index 9984268..c7173f2 100644 --- a/src/main/java/com/autonomouslogic/primes/Primorials.java +++ b/src/main/java/com/autonomouslogic/primes/Primorials.java @@ -135,7 +135,7 @@ public static LongStream allPossiblePrimes(long from) { if (from < 2) { throw new IllegalArgumentException("from must be at least 2"); } - return IntStream.rangeClosed(1, 8) + var mainStream = IntStream.rangeClosed(1, 8) .mapToObj(Primorials::ofOrderWithCoprimes) .filter(o -> ofOrder(o.getN() + 1) >= from) .flatMapToLong(order -> { @@ -149,6 +149,11 @@ public static LongStream allPossiblePrimes(long from) { } return stream; }); + if (from == 2) { + return LongStream.concat(LongStream.of(2), mainStream); + } else { + return mainStream; + } } public static void main(String[] args) { diff --git a/src/main/java/com/autonomouslogic/primes/TrialDivision.java b/src/main/java/com/autonomouslogic/primes/TrialDivision.java index d00b3e3..a139da8 100644 --- a/src/main/java/com/autonomouslogic/primes/TrialDivision.java +++ b/src/main/java/com/autonomouslogic/primes/TrialDivision.java @@ -8,15 +8,33 @@ public boolean isPrime(long number) { if (number == 2) { return true; } + var maxCheck = PrimeUtils.maxRequiredCheck(number); + + // This is so much faster than using the stream of possible primes below. It can probably be optimised. if (number % 2 == 0) { return false; } - var max = PrimeUtils.maxRequiredCheck(number); - for (int i = 3; i <= max; i += 2) { - if (number % i == 0) { + for (int n = 3; n <= maxCheck; n += 2) { + if (number % n == 0) { return false; } } + + // var iterator = Primorials.allPossiblePrimes().iterator(); + // while (iterator.hasNext()) { + // var n = iterator.next(); + // if (n > maxCheck) { + // break; + // } + // if (number % n == 0) { + // return false; + // } + // } + return true; + + // return Primorials.allPossiblePrimes() + // .takeWhile(n -> n <= maxCheck) + // .noneMatch(n -> number % n == 0); } } diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java index f13aec8..78df1f0 100644 --- a/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java +++ b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.stream.Collectors; +import java.util.stream.LongStream; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -49,6 +50,7 @@ public static Stream possiblePrimesTests() { @Test void shouldReturnAllPossiblePrimes() { var expected = Stream.of( + LongStream.of(2), Primorials.ofOrderWithCoprimes(1).possiblePrimes().takeWhile(n -> n < 6), Primorials.ofOrderWithCoprimes(2).possiblePrimes().takeWhile(n -> n < 30), Primorials.ofOrderWithCoprimes(3).possiblePrimes().takeWhile(n -> n < 200)) From 4bc9d406a1001cb372ef284e5800b29e5bd48cc3 Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Thu, 24 Apr 2025 02:12:29 +0900 Subject: [PATCH 13/14] Trying to speed up Primorial possible prime generation and somehow managed to break it in the process --- .../autonomouslogic/primes/Primorials.java | 21 +++++++++++++--- .../autonomouslogic/primes/TrialDivision.java | 25 ++++++++++--------- .../primes/PrimorialsTest.java | 7 ++++++ .../primes/TrialDivisionTest.java | 1 + 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/autonomouslogic/primes/Primorials.java b/src/main/java/com/autonomouslogic/primes/Primorials.java index c7173f2..b7e6001 100644 --- a/src/main/java/com/autonomouslogic/primes/Primorials.java +++ b/src/main/java/com/autonomouslogic/primes/Primorials.java @@ -39,6 +39,13 @@ */ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Primorials { + /** + * The maximum order that will be cached and used in {@link #allPossiblePrimes(long)}. + */ + private static final int MAX_ORDER = 3; + + private static final Order[] ORDER_CACHE = new Order[MAX_ORDER + 1]; + @Value @AllArgsConstructor(access = AccessLevel.PROTECTED) public static class Order { @@ -96,6 +103,10 @@ public static long ofOrder(int n) { * @return */ public static Primorials.Order ofOrderWithCoprimes(int n) { + if (n <= MAX_ORDER && ORDER_CACHE[n] != null) { + return ORDER_CACHE[n]; + } + var primes = Arrays.stream(PrimeList.PRIMES).limit(n).toArray(); long product = 1; for (int prime : primes) { @@ -114,7 +125,11 @@ public static Primorials.Order ofOrderWithCoprimes(int n) { .map(num -> num - finalProduct) .toArray(); var c = primes.length == 0 ? 1 : primes[primes.length - 1]; - return new Primorials.Order(n, c, product, offsets); + var order = new Primorials.Order(n, c, product, offsets); + if (n <= MAX_ORDER) { + ORDER_CACHE[n] = order; + } + return order; } /** @@ -135,11 +150,11 @@ public static LongStream allPossiblePrimes(long from) { if (from < 2) { throw new IllegalArgumentException("from must be at least 2"); } - var mainStream = IntStream.rangeClosed(1, 8) + var mainStream = IntStream.rangeClosed(1, MAX_ORDER) .mapToObj(Primorials::ofOrderWithCoprimes) .filter(o -> ofOrder(o.getN() + 1) >= from) .flatMapToLong(order -> { - if (order.getProduct() == 8) { + if (order.getN() == MAX_ORDER) { return order.possiblePrimes(); } var nextK = ofOrder(order.getN() + 1); diff --git a/src/main/java/com/autonomouslogic/primes/TrialDivision.java b/src/main/java/com/autonomouslogic/primes/TrialDivision.java index a139da8..3869c6e 100644 --- a/src/main/java/com/autonomouslogic/primes/TrialDivision.java +++ b/src/main/java/com/autonomouslogic/primes/TrialDivision.java @@ -14,23 +14,24 @@ public boolean isPrime(long number) { if (number % 2 == 0) { return false; } - for (int n = 3; n <= maxCheck; n += 2) { - if (number % n == 0) { - return false; - } - } - - // var iterator = Primorials.allPossiblePrimes().iterator(); - // while (iterator.hasNext()) { - // var n = iterator.next(); - // if (n > maxCheck) { - // break; - // } + // for (int n = 3; n <= maxCheck; n += 2) { // if (number % n == 0) { // return false; // } // } + var iterator = Primorials.allPossiblePrimes().iterator(); + while (iterator.hasNext()) { + var n = iterator.next(); + System.out.println("n=" + n); + if (n > maxCheck) { + break; + } + if (number % n == 0) { + return false; + } + } + return true; // return Primorials.allPossiblePrimes() diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java index 78df1f0..8ca08d1 100644 --- a/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java +++ b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java @@ -58,6 +58,7 @@ void shouldReturnAllPossiblePrimes() { .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); var actual = Primorials.allPossiblePrimes() + .peek(n -> System.out.println(n)) .takeWhile(n -> n <= 200) .mapToObj(String::valueOf) .collect(Collectors.joining("\n")); @@ -97,4 +98,10 @@ public static Stream primorialTests() { Arguments.of(4, 210), Arguments.of(5, 2310)); } + + @Test + void speedTest() { + var sum = Primorials.allPossiblePrimes().takeWhile(n -> n < 104729).sum(); + assertEquals(1058956954, sum); + } } diff --git a/src/test/java/com/autonomouslogic/primes/TrialDivisionTest.java b/src/test/java/com/autonomouslogic/primes/TrialDivisionTest.java index 95f1a33..53a4628 100644 --- a/src/test/java/com/autonomouslogic/primes/TrialDivisionTest.java +++ b/src/test/java/com/autonomouslogic/primes/TrialDivisionTest.java @@ -13,6 +13,7 @@ public class TrialDivisionTest { void testTrialDivision() { var test = new TrialDivision(); PrimeTestUtil.primeTestNumbers() + .filter(t -> t.number == 49) .forEach(n -> assertEquals(n.isPrime, test.isPrime(n.number), Long.toString(n.number))); } From ccdb8d3f39a2f60521ae9806f333493a495114ef Mon Sep 17 00:00:00 2001 From: Kenneth Jorgensen Date: Fri, 25 Apr 2025 16:24:06 +0900 Subject: [PATCH 14/14] Debugging --- .../java/com/autonomouslogic/primes/Primorials.java | 12 ++++++++---- .../com/autonomouslogic/primes/PrimorialsTest.java | 10 +++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/autonomouslogic/primes/Primorials.java b/src/main/java/com/autonomouslogic/primes/Primorials.java index b7e6001..5f858ff 100644 --- a/src/main/java/com/autonomouslogic/primes/Primorials.java +++ b/src/main/java/com/autonomouslogic/primes/Primorials.java @@ -154,14 +154,18 @@ public static LongStream allPossiblePrimes(long from) { .mapToObj(Primorials::ofOrderWithCoprimes) .filter(o -> ofOrder(o.getN() + 1) >= from) .flatMapToLong(order -> { - if (order.getN() == MAX_ORDER) { - return order.possiblePrimes(); + System.out.printf("Order: %s%n", order); + var stream = order.possiblePrimes(); + if (order.getN() < MAX_ORDER) { + System.out.println("not MAX_ORDER"); + var nextK = ofOrder(order.getN() + 1); + System.out.printf("nextK: %s%n", nextK); + stream = order.possiblePrimes().takeWhile(num -> num < nextK); } - var nextK = ofOrder(order.getN() + 1); - var stream = order.possiblePrimes().takeWhile(num -> num < nextK); if (order.getProduct() < from) { stream = stream.filter(n -> n >= from); } + System.out.println("return stream"); return stream; }); if (from == 2) { diff --git a/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java index 8ca08d1..e144765 100644 --- a/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java +++ b/src/test/java/com/autonomouslogic/primes/PrimorialsTest.java @@ -56,12 +56,16 @@ void shouldReturnAllPossiblePrimes() { Primorials.ofOrderWithCoprimes(3).possiblePrimes().takeWhile(n -> n < 200)) .flatMapToLong(s -> s) .mapToObj(String::valueOf) - .collect(Collectors.joining("\n")); + .toList(); + // .collect(Collectors.joining("\n")); var actual = Primorials.allPossiblePrimes() .peek(n -> System.out.println(n)) - .takeWhile(n -> n <= 200) + // .takeWhile(n -> n <= 200) .mapToObj(String::valueOf) - .collect(Collectors.joining("\n")); + .limit(expected.size()) + .toList(); + // .count(); + // .collect(Collectors.joining("\n")); assertEquals(expected, actual); }