1. 程式人生 > >Project Euler Problem 60 (C++和Python)

Project Euler Problem 60 (C++和Python)

Problem 60 : Prime pair sets

The primes 3, 7, 109, and 673, are quite remarkable. By taking any two primes and concatenating them in any order the result will always be prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of these four primes, 792, represents the lowest sum for a set of four primes with this property.

Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime.

C++ 程式碼

#include <iostream>
#include <string>
#include <set>
#include <vector>
#include <iterator>
#include <cmath>
#include <cassert>
    
using
namespace std; #define CPP_11 //#define UNIT_TEST class PE0060 { private: vector<int> m_primes_v = {}; bool checkPrime(int number); void getPrimesVector(int max); vector<int> getDigits(int number); int getNumberByDigits(vector<int>& digits); bool checkConcatenatedPrimes
(int prime1, int prime2); public: PE0060() { getPrimesVector(10000); } bool checkPrimesPair(int prime1, int prime2); int findLowestSumOfFivePrimes(); }; bool PE0060::checkPrime(int number) { double squareRoot = sqrt((double)number); if (number < 2 || number % 2 == 0 && number != 2) { return false; } for (int i = 3; i <= (int)squareRoot; i += 2) // 3, 5, 7, ...(int)squareRoot { if (number % i == 0) { return false; } } return true; } vector<int> PE0060::getDigits(int number) { vector<int>digit_vec; while (number > 0) { digit_vec.push_back(number % 10); // 197 => digits: 7, 9, 1 number /= 10; } return digit_vec; } int PE0060::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, 1 => 197 iter++; } return number; } bool PE0060::checkConcatenatedPrimes(int prime1, int prime2) { #ifndef CPP_11 vector<int> prime1_vec = getDigits(prime1); vector<int> prime2_vec = getDigits(prime2); vector<int>::iterator iter; for (iter = prime1_vec.begin(); iter != prime1_vec.end(); iter++) { prime2_vec.push_back(*iter); } int number = getNumberByDigits(prime2_vec); return checkPrime(number); #else string s = to_string(prime1) + to_string(prime2); return checkPrime(stoi(s)); // prime1:109, prime2:7, concat number: 1097 #endif } bool PE0060::checkPrimesPair(int prime1, int prime2) { if (false == checkConcatenatedPrimes(prime1, prime2) || false == checkConcatenatedPrimes(prime2, prime1)) { return false; } return true; } void PE0060::getPrimesVector(int max) { for (int n = 3; n < max; n++) { if (true == checkPrime(n)) { m_primes_v.push_back(n); } } } int PE0060::findLowestSumOfFivePrimes() { int size = m_primes_v.size(); for (int i = 1; i < size - 4; i++) // skip first prime 2 { for (int j = i + 1; j < size - 3; j++) { if (false == checkPrimesPair(m_primes_v[i], m_primes_v[j])) { continue; } for (int k = j + 1; k < size - 2; k++) { if (false == checkPrimesPair(m_primes_v[i], m_primes_v[k]) || false == checkPrimesPair(m_primes_v[j], m_primes_v[k])) { continue; } for (int n = k + 1; n < size - 1; n++) { if (false == checkPrimesPair(m_primes_v[i], m_primes_v[n]) || false == checkPrimesPair(m_primes_v[j], m_primes_v[n]) || false == checkPrimesPair(m_primes_v[k], m_primes_v[n])) { continue; } for (int m = n + 1; m < size; m++) { if (false==checkPrimesPair(m_primes_v[i],m_primes_v[m]) || false==checkPrimesPair(m_primes_v[j],m_primes_v[m]) || false==checkPrimesPair(m_primes_v[k],m_primes_v[m]) || false==checkPrimesPair(m_primes_v[n],m_primes_v[m])) { continue; } #ifdef UNIT_TEST cout << "Five primes chain: " << m_primes_v[i] << ", "; cout << m_primes_v[j] << ", " << m_primes_v[k] << ", "; cout << m_primes_v[n] << ", " << m_primes_v[m] << endl; #endif return (m_primes_v[i] + m_primes_v[j] + \ m_primes_v[k] + m_primes_v[n] + m_primes_v[m]); } } } } } return 0; } int main() { PE0060 pe0060; assert(true == pe0060.checkPrimesPair(109, 7)); int sum = pe0060.findLowestSumOfFivePrimes(); cout << "The lowest sum for a set of five primes is " << sum << endl; return 0; }

Python

import itertools

def check_prime(x):
    """check whether integer x is a prime """
    if x < 2 or (x != 2 and x%2 == 0):
        return False
    for i in range (3, int(x**0.5)+1, 2):
        if 0 == x % i:
            return False
    return True

def create_primes_sieve(n):
    """ Returns a list of primes < n """
    sieve = [True] * int(n/2)

    for i in range(3, int(n**0.5)+1, 2):
        if True == sieve[int(i/2)]:
            sieve[int(i*i/2)::i] = [False] * (int((n-i*i-1)/(2*i))+1)

    return [2] + [ 2*i+1 for i in range(1, int(n/2)) if True == sieve[i] ] 
    
def make_primes_chain(chain, primes_list, set_size):
    """use recusive method to find five primes chain """
    if len(chain) == set_size:
        return chain
 
    for p in primes_list:
        if p > chain[-1] and True == check_all_concatenated_primes(chain+[p]):
            new_chain = make_primes_chain(chain+[p], primes_list, set_size)
            if new_chain:
                return new_chain
    return []  
            
def check_all_concatenated_primes(chain):
    """
    check whether any two primes in chain can concatenate a prime 
 
    return all(check_prime(int(str(p[0])+str(p[1]))) \
        for p in iter.permutations(chain, 2))
    """
    for p in itertools.permutations(chain, 2):
        if False == check_prime(int(str(p[0])+str(p[1]))):
            return False
    return True

def main():
    primes_list = create_primes_sieve(10000)

    chain = []
    while not chain:
        chain = make_primes_chain([primes_list.pop(0)], primes_list, 5)

    print("The lowest sum for a set of five primes", chain, "is", sum(chain))
    
if  __name__ == '__main__':
    main()