This method will take in a Long
and return a LongStream
of prime numbers for any digit passed to the method.
factors.java
public LongStream factors(long x){
LongStream factorStream = LongStream.range(1, x+1).filter(n -> x%n == 0);
return factorStream;
}
Utilizing the above method to find common factors first is ok.
primeFactors.java
public LongStream primeFactors(long x){
LongStream primeFactorStream = factors(x).filter(n -> factors(n).count() == 0);
//doesn't work as factors.java returns a LongStream, which might include non-prime factors, which will not equate to zero.
return primeFactorStream;
}
I understand this should be easily circumvented with the use of a simple isPrime() method with a predicate, but is there a way to do the same thing for for prime factors but only with a single method?
If you want to do it in a single method without the aid of an existing test-for-prime method, you can do it like
public static LongStream primeFactors(long x) {
return LongStream.rangeClosed(2, x)
.filter(n -> x % n == 0)
.filter(n -> LongStream.rangeClosed(2, n/2).noneMatch(i -> n%i==0));
}
You can test the method like
IntStream.concat(IntStream.rangeClosed(2, 15), IntStream.rangeClosed(90, 110))
.forEach(number -> System.out.printf("%3d = %s%n", number,
primeFactors(number)
.mapToObj(d -> {
int p = 0;
for(long l = number; l%d == 0; l /= d, p++) l++;
return p == 1? String.valueOf(d): d + "^" + p;
})
.collect(Collectors.joining(" * ")))
);
}
2 = 2
3 = 3
4 = 2^2
5 = 5
6 = 2 * 3
7 = 7
8 = 2^3
9 = 3^2
10 = 2 * 5
11 = 11
12 = 2^2 * 3
13 = 13
14 = 2 * 7
15 = 3 * 5
90 = 2 * 3^2 * 5
91 = 7 * 13
92 = 2^2 * 23
93 = 3 * 31
94 = 2 * 47
95 = 5 * 19
96 = 2^5 * 3
97 = 97
98 = 2 * 7^2
99 = 3^2 * 11
100 = 2^2 * 5^2
101 = 101
102 = 2 * 3 * 17
103 = 103
104 = 2^3 * 13
105 = 3 * 5 * 7
106 = 2 * 53
107 = 107
108 = 2^2 * 3^3
109 = 109
110 = 2 * 5 * 11
Needless to say, this isn’t the most efficient approach…
You could make use of the BigInteger
's isProbablePrime()
method to check if your factors are prime:
public static LongStream primeFactors(long x){
LongStream primeFactorStream = factors(x)
.filter(n -> new BigInteger(String.valueOf(n)).isProbablePrime(10));
return primeFactorStream;
}
For primeFactors(26).forEach(System.out::println);
it returns 2 13
.
Without memoization, and using LongStream
you could apply few simple performance improvements like for stream of prime factors producing a stream of numbers up to x/2:
public static LongStream factors(long x){
return LongStream.rangeClosed(2, x/2).filter(n -> x % n == 0);
}
public static LongStream primeFactors(long x){
return LongStream.rangeClosed(2, x/2)
.filter(n -> x % n == 0).filter(n -> factors(n).count() == 0);
}
Which for very large x will matter.
However this solution repeats the test of x % n == 0
for each n in each of 2 streams, which begs for memoization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With