project euler 35

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);
		}

	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值