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

Project Euler Problem 37

Problem 37 : Truncatable primes

The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3.

Find the sum of the only eleven primes that are both truncatable from left to right and right to left.

NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.

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

using namespace std;

#define UNIT_TEST

class PE0037
{
private:
    static const int
m_MAX = 1000000; // one million bool *m_Sieve; void createPrimeSieve(); int m_digits[10]; // save digits of number below one million bool checkPrime(int number) const; int getDigits(int number); int getNumberByDigits(vector<int>digits); int getNumberByDigits(int first,
int last); public: PE0037() { m_Sieve = new bool [m_MAX+1]; createPrimeSieve(); } ~PE0037() { delete [] m_Sieve; } bool checkTruncatablePrimes(int number); int getSumOfTruncatablePrimes(); }; // create a prime Sieve of Eratosthenes below max value void PE0037::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 PE0037::checkPrime(int number) const { return m_Sieve[number]; } int PE0037::getDigits(int number) { int numOfDigits = 0; while(number> 0) { m_digits[numOfDigits++] = number%10; // 3797 => digits: 7, 9, 7, 3 number /= 10; } return numOfDigits; } int PE0037::getNumberByDigits(vector<int>digits) { vector<int>::reverse_iterator iter=digits.rbegin(); int number = 0; while(iter!=digits.rend()) { number = number*10 + *iter; // digits: 7, 9, 7, 3 => 3797 iter++; } return number; } int PE0037::getNumberByDigits(int first, int last) { int number = 0; for(int i=last; i>=first; i--) { number = number*10 + m_digits[i]; // digits: 7, 9, 7, 3 => 3797 } return number; } bool PE0037::checkTruncatablePrimes(int number) { if (false == checkPrime(number)) { return false; } int numOfDigits = getDigits(number); #ifdef USE_VECTOR vector<int> digits_v(numOfDigits); digits_v.assign(m_digits, m_digits+numOfDigits); // work from right to left, e.g. 3797, 379, 37, and 3 because digits_v={7,9,7,3} vector<int>::iterator iter = digits_v.begin(); while (iter != digits_v.end()) { vector<int>dv(iter, digits_v.end()); int n = getNumberByDigits(dv); if (false == checkPrime(n)) { return false; } iter++; } // work from left to right, e.g. 3797, 797, 97, and 7 because digits_v={7,9,7,3} vector<int>::iterator iter1 = digits_v.end(); while (iter1 != digits_v.begin()) { vector<int> dv(digits_v.begin(), iter1); int n = getNumberByDigits(dv); if (false == checkPrime(n)) { return false; } iter1--; } #else for(int i=0; i<=numOfDigits-1; i++) { int n = getNumberByDigits(i, numOfDigits-1); if (false == checkPrime(n)) { return false; } } for(int i=numOfDigits-1; i>=0; i--) { int n = getNumberByDigits(0, i); if (false == checkPrime(n)) { return false; } } #endif return true; } int PE0037::getSumOfTruncatablePrimes() { int sumOfTruncatablePrimes = 0; int numOfTruncatablePrimes = 0; for(int number=10;numOfTruncatablePrimes<11;number++) { if (true == checkTruncatablePrimes(number)) { sumOfTruncatablePrimes += number; numOfTruncatablePrimes++; #ifdef UNIT_TEST cout << number << " is " << numOfTruncatablePrimes; cout << "th truncatable prime." << endl; #endif } } return sumOfTruncatablePrimes; } int main() { clock_t start = clock(); PE0037 pe0037; assert(true == pe0037.checkTruncatablePrimes(3797)); cout << "The sum of the only primes that are both truncatable" << endl; cout << "from left to right and right to left is " ; cout << pe0037.getSumOfTruncatablePrimes() << endl; clock_t finish = clock(); double duration = (double)(finish - start) / CLOCKS_PER_SEC; cout << "C/C++ application running time: " << duration << " seconds" << endl; return 0; }