Files
contests/projecteuler/060/main.cpp

174 lines
5.8 KiB
C++

/*
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 <iostream>
#include <chrono>
#include <vector>
#include <unordered_set>
#include <cmath>
using namespace std;
vector<unsigned int> sieve(int n){
if(n < 2) return vector<unsigned int>();
vector<bool> 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<unsigned int> 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<unordered_set<unsigned int>> aPriori(const vector<unordered_set<unsigned int>> & primePairs, const unordered_set<unsigned int> & primes){
if(primePairs.empty()) return vector<unordered_set<unsigned int>>();
int setSize = primePairs[0].size();
vector<unordered_set<unsigned int>> 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<unsigned int> 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<unsigned int> primes(primeVector.begin(), primeVector.end());
bool foundSum = false;
for(auto it = primeVector.begin(); it != primeVector.end(); ++it){
if(foundSum) break;
vector<int> candidateDoubles(it + 1, primeVector.end());
for(auto jt = candidateDoubles.begin(); jt != candidateDoubles.end(); ++jt){
if(foundSum) break;
if(match(*it, *jt)){
vector<int> 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<int> 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<int> 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::milliseconds>(chrono::high_resolution_clock::now() - start);
std::cout << (float)duration.count()/1000 << endl;
return 0;
}