/* 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. */ #include #include #include #include #include using namespace std; vector sieve(int n){ if(n < 2) return vector(); vector ns(n, true); for(int i = 2; i <= sqrt(n); ++i){ if(ns[i]){ int j = pow(i, 2); while(j < n){ ns[j] = false; j += i; } } } vector primes; for(size_t i = 2; i < ns.size(); ++i){ if(ns[i]) primes.push_back(i); } return primes; } // Wheel factorization primality test bool isPrime(const unsigned long long n){ if(n % 2 == 0 || n % 3 == 0 || n % 5 == 0){ return n == 2 || n == 3 || n == 5; } const unsigned int delta[] = {6, 4, 2, 4, 2, 4, 6, 2}; unsigned long long i = 7; int pos = 1; while(i*i <= n){ if(n % i == 0){ return false; } i += delta[pos]; pos = (pos + 1) & 7; } return n > 1; } int intLength(const unsigned long long n){ return trunc(log10(n)) + 1; } unsigned long long combine(const unsigned long long n, const unsigned long long m){ unsigned long long res = n; int mLength = intLength(m); res *= pow(10, mLength); res += m; return res; } bool match(unsigned long long n, unsigned long long m){ return isPrime(combine(n, m)) && isPrime(combine(m, n)); } // Assume that the size of all unordered sets is equal, otherwise this doesn't work // WARNING: this is not an efficient function and it might even be bugged vector> aPriori(const vector> & primePairs, const unordered_set & primes){ if(primePairs.empty()) return vector>(); int setSize = primePairs[0].size(); vector> result; for(size_t i = 0; i < primePairs.size(); ++i){ for(size_t j = min(i + 1, primePairs.size() - 1); j < primePairs.size(); ++j){ unordered_set combinationSet(primePairs[i]); for(int k : primePairs[j]){ combinationSet.insert(k); } if(combinationSet.size() == setSize + 1){ bool allPrimes = true; for(auto it = combinationSet.begin(); it != combinationSet.end(); ++it){ for(auto jt = combinationSet.begin(); jt != combinationSet.end(); ++jt){ if(it != jt){ int p1 = combine(*it, *jt), p2 = combine(*jt, *it); if(primes.find(p1) == primes.end() || primes.find(p2) == primes.end()){ allPrimes = false; break; } } } } if(allPrimes) result.push_back(combinationSet); } } } return result; } int main(){ std::cout << "Hello this is Patrick" << endl; auto start = chrono::high_resolution_clock::now(); auto primeVector = sieve(10000); // unordered_set primes(primeVector.begin(), primeVector.end()); bool foundSum = false; for(auto it = primeVector.begin(); it != primeVector.end(); ++it){ if(foundSum) break; vector candidateDoubles(it + 1, primeVector.end()); for(auto jt = candidateDoubles.begin(); jt != candidateDoubles.end(); ++jt){ if(foundSum) break; if(match(*it, *jt)){ vector candidateTriples(jt + 1, candidateDoubles.end()); for(auto kt = candidateTriples.begin(); kt != candidateTriples.end(); ++kt){ if(foundSum) break; if(match(*it, *kt) && match(*jt, *kt)){ vector candidateQuartets(kt + 1, candidateTriples.end()); for(auto lt = candidateQuartets.begin(); lt != candidateQuartets.end(); ++lt){ if(foundSum) break; if(match(*it, *lt) && match(*jt, *lt) && match(*kt, *lt)){ vector candidateQuintets(lt + 1, candidateQuartets.end()); for(auto mt = candidateQuintets.begin(); mt != candidateQuintets.end(); ++mt){ if(match(*it, *mt) && match(*jt, *mt) && match(*kt, *mt) && match(*lt, *mt)){ std::cout << *it << " " << *jt << " " << *kt << " " << *lt << " " << *mt << " equals: " << *it + *jt + *kt + *lt + *mt << endl; foundSum = true; break; } } // For checking the result of four // cout << *it << " " << *jt << " " << *kt << " " << *lt << endl; } } } } } } } auto duration = chrono::duration_cast(chrono::high_resolution_clock::now() - start); std::cout << (float)duration.count()/1000 << endl; return 0; }