1. 程式人生 > >Project Euler Problem 35

Project Euler Problem 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?

#include <iostream>
#include <vector>
#include <set>
#include <iterator>
#include <cmath>
#include <ctime>
#include <cassert>

using namespace std;

// #define UNIT_TEST
// #define USE_DIGITS_VECTOR

class PE0035
{
private:
    static const int m_MAX = 1000000;  // one millions
bool *m_Sieve; void createPrimeSieve(); bool checkPrime(long long number); bool checkDigitZero(int number); vector<int> getDigits(long int number); long getNumberByDigits(vector<int>& digits); bool checkRotationDigits(long int number); public: PE0035(
) { m_Sieve = new bool [m_MAX+1]; createPrimeSieve(); } ~PE0035() { delete [] m_Sieve; } int getCircularPrimes(int number); }; // create a prime Sieve of Eratosthenes below max value void PE0035::createPrimeSieve() { memset(m_Sieve, true, (m_MAX+1)*sizeof(bool)); m_Sieve[0] = m_Sieve[1] = false; for (int i=2; i<=(int)sqrt((double)m_MAX); i++) { if (true == m_Sieve[i]) { for (int j=i*i; j<m_MAX; j+=i) { m_Sieve[j] = false; } } } } bool PE0035::checkPrime(long long number) { long double squareRoot=sqrtl((long double)number); if (number<2 || number%2 == 0 && number>2) { return false; } for(long int i=3;i<=(long long)squareRoot;i+=2) // 3, 5, 7, ...(int)squareRoot { if (number % i == 0) { return false; } } return true; } vector<int> PE0035::getDigits(long int number) { vector<int> digit_vec; while(number> 0) { digit_vec.push_back(number%10); // 197 => reverse digits: 7, 9, 1 number /= 10; } return digit_vec; } long PE0035::getNumberByDigits(vector<int>& digits) { vector<int>::reverse_iterator iter=digits.rbegin(); long number = 0; while(iter!=digits.rend()) { number = number*10 + *iter; // digits: 7, 9, 1 => 197 iter++; } return number; } bool PE0035::checkRotationDigits(long int number) { #ifdef USE_DIGITS_VECTOR if (number > 10) { vector<int> digits_v; while(number> 0) { if (0 == number%10) { return false; } digits_v.push_back(number%10); // 197 => digits: 7, 9, 1 number /= 10; } vector<int>::iterator iter; int digit; for(unsigned int i=1; i<digits_v.size(); i++) { iter = digits_v.begin(); digit = *iter; digits_v.erase(iter); digits_v.push_back(digit); number = getNumberByDigits(digits_v); if (false == m_Sieve[number]) { return false; } } } #else // USE_DIGITS_ARRAY int digitsArray[6]; // max number 999999 int numOfDigits = 0; while (number > 0) { if (0 == number%10) { return false; } digitsArray[numOfDigits++] = number%10; number /= 10; } // note that digitsArray stores reverse digits of number // digitsArray[] = {1, 3, 3, 9, 9, 9} while number is 999331 for (int i=numOfDigits-1; i>0; i--) { number = 0; for (int j=numOfDigits+i-1; j>=i; j--) { number = number*10 + digitsArray[j%numOfDigits]; } if (false == m_Sieve[number]) { return false; } } #endif return true; } int PE0035::getCircularPrimes(int number=m_MAX) { int numOfCircularPrimes = 0; for(long n=2; n<number; n++) { if (true==m_Sieve[n] && true==checkRotationDigits(n)) { #ifdef UNIT_TEST cout << "The number " << n << " is called a circular prime." << endl; #endif numOfCircularPrimes++; } } return numOfCircularPrimes; } int main() { clock_t start = clock(); PE0035 pe0035; assert(13 == pe0035.getCircularPrimes(100)); cout << "There are " << pe0035.getCircularPrimes(); cout << " circular primes below one million" << endl; clock_t finish = clock(); double duration = (double)(finish - start) / CLOCKS_PER_SEC; cout << "C/C++ application running time: " << duration << " seconds" << endl; return 0; }