おそらくもう少し複雑ですが、これまでのところ機能しており、Javaで見つけた最速の(そして最小の)素数ジェネレーターを使用しています。
まず、値が素数であるかどうかをテストするために必要な素数ジェネレーターを取得しました。ジェネレーターを使用するため(これはナイーブメソッドよりも10倍高速です)、キャッシュリストを使用します。
/**
* Sieve of Sundaram prime number generator
* Implementation following the Sieve of Sundaram to generate prime numbers
*
* @see http://en.wikipedia.org/wiki/Sieve_of_Sundaram
*/
static public class SundaramSievePrimeGenerator {
public String getName() { return "Sieve of Sundaram generator"; }
public int[] findPrimes(int max) {
int n = max/2;
boolean[] isPrime = new boolean[max];
Arrays.fill(isPrime, true);
for (int i=1; i<n; i++) {
for (int j=i; j<=(n-i)/(2*i+1); j++) {
isPrime[i+j+2*i*j] = false;
}
}
int[] primes = new int[max];
int found = 0;
if (max > 2) {
primes[found++] = 2;
}
for (int i=1; i<n; i++) {
if (isPrime[i]) {
primes[found++] = i*2+1;
}
}
return Arrays.copyOf(primes, found);
}
}
次に、次の素因数のリストを実際に取得するために必要な2つの方法がありますn
。
/**
* Reuse an instance of the SundaramSievePrimeGenerator
*/
static public List<Integer> findPrimeFactors(int n, SundaramSievePrimeGenerator g) {
ArrayList<Integer> primeFactors = new ArrayList<Integer>();
int[] primes = g.findPrimes(n+1);
int v;
// debug
//System.out.print("** primes found : ");
//for (int a : primes) {
// System.out.print(" " + a);
//}
//System.out.println();
if (primes[primes.length-1] == n) {
primeFactors.add(n);
} else {
int max = primes.length - 1;
for (int i=max; i>=0; i--) {
primeFactors.add(primes[i]);
if (testPrimeFactor(n, primes[i], primes, i, primeFactors)) {
break; // we found our solution
}
primeFactors.clear();
}
}
return primeFactors;
}
/**
* Recursive method initially called by findPrimeFactors(n, g)
*/
static private boolean testPrimeFactor(int n, int v, int[] primes, int index, List<Integer> factors) {
int v2 = v * primes[index];
if (v2 == n) {
factors.add(primes[index]);
return true;
} else if (v2 > n) {
if (index > 0) {
return testPrimeFactor(n, v, primes, index-1, factors);
} else {
return false;
}
} else {
while (index > 0) {
factors.add(primes[index]);
if (testPrimeFactor(n, v2, primes, index, factors)) {
return true;
}
factors.remove(factors.size()-1); // no good, remove added prime
v2 = v * primes[--index];
}
return false; // at this point, we are still below n... so no good
}
}
そして最後に、私たちのテストケース:
int n = 1025;
SundaramSievePrimeGenerator generator = new SundaramSievePrimeGenerator();
List<Integer> factors = findPrimeFactors(n, generator);
if (factors.isEmpty()) {
System.out.println("No prime factors found for " + n);
} else {
System.out.println(n + " is composed of " + factors.size() + " prime factors");
int v = 1;
for (int i : factors) {
v *= i;
System.out.print(" " + i);
}
System.out.println(" = " + v);
}
たとえば、上記のコードは次のように生成されます。
1025 is composed of 3 prime factors
41 5 5 = 1025
そして、変更n = 81
すると、
81 is composed of 4 prime factors
3 3 3 3 = 81