Project Euler Problem 37

版权声明:代码属于原创,转载请联系作者并注明出处。 https://blog.csdn.net/weixin_43379056/article/details/83414085

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

猜你喜欢

转载自blog.csdn.net/weixin_43379056/article/details/83414085