Problem 35
Circular primes
The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime.
There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97.
How many circular primes are there below one million?
圆周素数
197被称为圆周素数,因为将它逐位旋转所得到的数:197/971和719都是素数。
小于100的圆周素数有十三个:2、3、5、7、11、13、17、31、37、71、73、79和97。
小于一百万的圆周素数有多少个?
package projecteuler;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.junit.Test;
public class Prj35 {
/**
* The number, 197, is called a circular prime because all rotations of the
* digits: 197, 971, and 719, are themselves prime.
*
* There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37,
* 71, 73, 79, and 97.
*
* How many circular primes are there below one million?
*/
@Test
public void test() {
System.out.println(Calculator.calculateList(1000000));
// System.out.println(Calculator.calculate(1000000));
}
public static class Calculator {
public static int calculateList(int upLimit) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 2; i <= upLimit; i++) {
if (checkIsPrime(i)) {
list.add(i);
}
}
Set<Integer> primeSet = filterPrimes(list);
List<Integer> ret = new ArrayList<Integer>();
Iterator<Integer> iterator = primeSet.iterator();
while (iterator.hasNext()) {
int val = iterator.next();
if (val < 10) {
ret.add(val);
continue;
}
int bit = 1;
int tmpVal = val;
while (tmpVal >= 10) {
bit++;
tmpVal /= 10;
}
boolean filter = false;
tmpVal = val;
for (int i = 0; i < bit; i++) {
tmpVal = (int) (tmpVal % Math.pow(10, bit - 1) * 10 + tmpVal
/ Math.pow(10, bit - 1));
if (!primeSet.contains(tmpVal)) {
filter = true;
break;
}
}
if (!filter) {
ret.add(val);
}
}
System.out.println(ret);
return ret.size();
}
private static Set<Integer> filterPrimes(List<Integer> primeList) {
Set<Integer> set = new HashSet<Integer>();
for (Integer val : primeList) {
if (val < 10) {
set.add(val);
continue;
}
int tmpVal = val;
boolean hasZeroTwoFive = false;
while (tmpVal >= 10) {
tmpVal /= 10;
// 103 031 310
if (tmpVal % 10 == 0 || tmpVal % 10 == 2
|| tmpVal % 10 == 4 || tmpVal % 10 == 6
|| tmpVal % 10 == 8 || tmpVal % 10 == 5) {
hasZeroTwoFive = true;
break;
}
}
if (!hasZeroTwoFive) {
set.add(val);
continue;
}
}
return set;
}
private static boolean checkIsPrime(int val) {
int num = Math.abs(val);
if (num >= 10) {
for (int i = 2; i <= Math.sqrt(num); i++) {
if (num % i == 0) {
return false;
}
}
return true;
} else {
if (num == 2 || num == 3 || num == 5 || num == 7) {
return true;
}
return false;
}
}
public static int calculate(int upLimit) {
BitSet bitMap = new BitSet(upLimit + 1);
bitMap.set(0);
bitMap.set(1);
int startId = 0;
while (true) {
startId = getNext(startId + 1, upLimit, bitMap);
System.out.println(startId);
if (startId == -1) {
break;
}
for (int i = startId + 1; i < upLimit; i++) {
if (i % startId == 0) {
setBit(i, true, bitMap);
}
}
}
checkCircular(bitMap, upLimit);
int count = 0;
int fromId = 0;
while (-1 != (fromId = bitMap.nextClearBit(fromId))) {
count++;
}
return count;
}
private static void checkCircular(BitSet bitMap, int upLimit) {
int startId = 0;
for (;;) {
startId = bitMap.nextClearBit(startId);
if (startId < 10) {
continue;
} else {
int val = startId;
int bit = 1;
int tmpVal = val;
boolean hasZeroTwoFive = false;
while (tmpVal >= 10) {
bit++;
tmpVal /= 10;
// 103 031 310
if (tmpVal % 10 == 2 || tmpVal % 10 == 0
|| tmpVal % 10 == 5) {
hasZeroTwoFive = true;
break;
}
}
if (hasZeroTwoFive) {
setBit(startId, true, bitMap);
continue;
}
boolean isCircular = true;
for (int i = 0; i < bit; i++) {
val = (int) (val % Math.pow(10, bit - 1) * 10 + val
/ Math.pow(10, bit - 1));
if (bitMap.get(val)) {
isCircular = false;
break;
}
}
if (!isCircular) {
val = startId;
for (int i = 0; i < bit; i++) {
val = (int) (val % Math.pow(10, bit - 1) * 10 + val
/ Math.pow(10, bit - 1));
if (val < upLimit) {
bitMap.set(val);
}
}
continue;
}
}
}
}
public static void setBit(int id, boolean isPrime, BitSet bitMap) {
bitMap.set(id, isPrime);
}
public static int getNext(int startId, int upLimit, BitSet bitMap) {
return bitMap.nextClearBit(startId);
}
}
}