diff --git a/puzzles/interviews/training/goldbachs_conjecture.cpp b/puzzles/interviews/training/goldbachs_conjecture.cpp index 79513df..3092609 100644 --- a/puzzles/interviews/training/goldbachs_conjecture.cpp +++ b/puzzles/interviews/training/goldbachs_conjecture.cpp @@ -3,68 +3,94 @@ #include #include #include +#include -using namespace std; +/* + Given an even number ( greater than 2 ), return two prime numbers whose + sum will be equal to given number. -static std::vector GetPrimes(const size_t n) { - std::vector primes; - std::vector lp(n + 1, 0); +NOTE A solution will always exist. read Goldbach’s conjecture -for (auto i = 2u; i <= n; ++i) { - if (lp[i] == 0) { - lp[i] = i; - primes.push_back(i); +Example: + + +Input : 4 +Output: 2 + 2 = 4 + +If there are more than one solutions possible, return the lexicographically +smaller solution. +*/ + +/* + * My understanding is: + * The first solution time complexity is O(n^2/log_n) + O(n) memory complexity. + * The second solution id O(n^2) complexity + O(0) memory complexity. + */ +#define SOLUTION 1 + +#if SOLUTION == 1 + +std::vector primes; +std::unordered_set primes_set; + +void init_primes(const size_t n) +{ + + std::vector prime_table(n/2+1, true); // Only odd numbers. + primes.push_back(2); + + for (auto p = 3; p <= n; p+=2) { + if ( prime_table[p/2] ) { + primes.push_back(p); + for ( int j = p*3; j <= n; j+=p*2 ) { + prime_table[j/2] = false; + } + } } - for (auto j = 0u; j < primes.size() && primes[j] <= lp[i] && i * primes[j] <= n; ++j) - lp[i * primes[j]] = primes[j]; -} -return primes; + primes_set.insert(primes.begin(), primes.end()); } -inline bool is_prime( int n, const vector& primes ){ - int sqrt_n = floor(sqrt(double(n))); - for ( int i = 0; i < primes.size() && primes[i] <= sqrt_n; ++i ){ - if ( n % primes[i] == 0 ) { +std::vector primesum(int A) +{ + for ( int p : primes ){ + if ( primes_set.find(A-p) != primes_set.end() ) { + return {p, A-p}; + } + } + + return {}; +} + +#elif SOLUTION == 2 + +bool is_prime(int a) +{ + if ( a <2 ) + return false; + + int end = std::floor(std::sqrt(a)); + for ( int i = 2; i <= end; ++i ){ + if ( a % i == 0) { return false; } } return true; } -vector primesum(int A) { +std::vector primesum(int A) +{ - vector primes; - -#if 0 - for ( int i = 2; i < A; ++i){ - if ( is_prime(i,primes) ){ - primes.push_back(i); + for ( int i = 2; i < A; ++i) { + if ( is_prime(i) && is_prime(A-i) ){ + return {i,A-i}; } } -#endif - - primes = GetPrimes(A); - -#if 1 - unordered_set primes_set(primes.begin(),primes.end()); - for ( int i = 0; i < primes.size(); ++i ){ - if ( primes_set.find(A-primes[i]) != primes_set.end() ) { - return {primes[i], A-primes[i]}; - } - } -#else - for ( int i = 0; i < primes.size(); ++i ) { - auto it = std::lower_bound(primes.begin(), primes.end(), A - primes[i]); - if ( it != primes.end() && *it == A-primes[i] ) { - return {primes[i], A-primes[i]}; - } - } -#endif - - return {}; + return {}; } +#endif + void solve_and_print(int A){ auto r = primesum(A); std::cout << r[0] << ' ' << r[1] << std::endl; @@ -72,8 +98,23 @@ void solve_and_print(int A){ int main() { + auto begin = std::chrono::high_resolution_clock::now(); + +#if SOLUTION == 1 + init_primes(16777218); +#endif + solve_and_print(4); solve_and_print(10); solve_and_print(16777214); + solve_and_print(16777218); + + for ( int i = 4; i < 1000000; i+=2 ){ + primesum(i); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration seconds = end - begin; + std::cout << "Time: " << seconds.count() << std::endl; }