I'm writing a function called largestTwinPrime where it takes in 2 numbers and finds the largest twin prime number between the two. My program works however when the user enters a large enough number the program becomes an infinite loop. For example:
largestTwinPrime(0, 15485661) would give me this error "Program exceeded its time limit and was stopped (possible infinite loop)".
largestTwinPrime(1, 18) would output 17.
This is the code I have and thanks for the help!
(isPrime)
int isPrime(int num){
if(num <= 1) return 0;
for (int i = 2; i * i <= num; i++){
if (num % i == 0) return 0;
}
return 1;
}
(isTwinPrime)
bool isTwinPrime(int n){
if(n <= 1) return 0;
if(isPrime(n+2)==true && isPrime(n)==true){
return 1;
} else if(isPrime(n-2)==true && isPrime(n)==true){
return 1;
} else{
return 0;
}
}
(largestTwinPrime)
int largestTwinPrime(int a, int b){
int answer=0;
while(a <= b){
for(int i = a; i <= b; i++){
if(isTwinPrime(i)== true){
answer = i;
}
}
a++;
}
if(answer==0) return -1;
else return answer;
}
Your code has a very poor complexity. Your code is invoking isTwinPrime O(n2) times which totals over O(n2.5). This makes it look like an infinite loop:
while(a <= b){ // O(N) iterations
for(int i = a; i <= b; i++){
// times O(N) = O(N**2)
if(isTwinPrime(i)== true){ // The call is over O(sqrt(N))
answer = i;
}
}
a++;
}
The correct code is:
int largestTwinPrime(int a, int b){
int answer=0;
if (b < 5) return -1;
// A twin prime is odd, so go over odd values.
if (b %2 == 0) b--;
for(int i = b; i >= a; i-=2){
if(isTwinPrime(i))
return i;
}
return -1;
}
Complexity is lower by a factor of O(N).
EDIT
Also, your isPrime is inefficient. Better to fill a vector of primes below sqrt(N) (using the Sieve of Eratosthenes), and use that to speed up the validation of primes.
Related
the code is showing wrong results...it is showing 15,21 and many other odd numbers as prime but they are not...how to fix the problem?..what code should I write in main section[inside int main()]?
#include<bits/stdc++.h>
using namespace std;
#define M 1000000
bool marked[M];
bool sieve(int n)
{
for (int i = 3; i * i <= n; i += 2)
{
if (marked[i] == false)
{
for (int j = i * i; j <= n; j += i + i)
{
marked[j] = true;
}
}
}
}
bool isPrime(int n)
{
if (n < 2)
return false;
if (n == 2)
return true;
if (n % 2 == 0)
return false;
return marked[n] == false;
}
int main()
{
int i,j,k,n,m;
cin>>n;
for(i=0; i<n; i++)
{
cin>>m;
if(isPrime(m))
cout<<"prime"<<endl;
else
cout<<"N"<<endl;
}
}
Is the wrong answer coming due to not properly using or calling functions?.....in this case what should be done.....
My guess is that, since you never call the sieve function, your marked array never gets filled. Since marked is not dynamically allocated, it is zeroed out within your program. Hence, in your isPrime function, all odd numbers will cascade through your if statements and then hit the part where marked[n] == false which would return true since marked[n] is 0 for all of its entries, which is equivalent to the boolean false.
You might want to figure out where it would be best to run the sieve function.
You have wrong increment here:
for (int j = i * i; j <= n; j += i + i)
You need to increase j by i, but you actually increase in by 2*i. Anyway I agree with the previous answer that you never call sieve.
So I have the following problem. They give me an array w/ n numbers and I have to print if it contains any prime numbers using "Divide et Impera". I solved the problem but it gets only 70/100 because it isn't efficient(they say).
#include <iostream>
using namespace std;
bool isPrime(int x){
if(x == 2) return false;
for(int i = 2; i <= x/2; ++i)
if(x%i==0) return false;
return true;
}
int existaP(int a[], int li, int ls){
if(li==ls)
if(isPrime(a[li]) == true) return 1;
else return 0;
else return existaP(a, li, (li+ls)/2)+existaP(a, (li+ls)/2+1, ls);
}
int main(){
int n, a[10001];
cin >> n;
for(int i = 1; i<=n; ++i) cin >> a[i];
if(existaP(a,1,n) >= 1) cout << "Y";
else cout << "N";
return 0;
}
The lowest hanging fruit here is your stopping conditional
i <= x/2
which can be replaced with
i * i <= x
having taken care to ensure you don't overflow an int.This is because you only need to go up to the square root of x, rather than half way. Perhaps i <= x / i is better still as that avoids the overflow; albeit at the expense of a division which can be relatively costly on some platforms.
Your algorithm is also defective for x == 2 as you have the incorrect return value. It would be better if you dropped that extra test, as the ensuing loop covers it.
Here is an efficinent way to check prime number.
bool isPrime(int num) {
if(num <= 1) return false;
if (num <= 3) return true;
int range = sqrt(num);
// This is checked so that we can skip
// middle five numbers in below loop
if (num % 2 == 0 || num % 3 == 0)
return false;
for (int i = 5; i <= range; i += 6)
if (num % i == 0 || num % (i + 2) == 0)
return false;
return true;
}
A stander way(maybe..?) is just check from i = 0 to the sqrt(number)
bool isPrime(int num){
if(num == 1) return false;
for(int i = 2;i<=sqrt(num);i++){
if(num % i == 0) return false;
}
return true;
}
bool isprime(int x)
{
if(x <= 1) return false;
if(x == 2 || x == 3) return true;
if(x % 2 == 0 || x % 3 == 0) return false;
if((x - 1) % 6 != 0 && (x + 1) % 6 != 0) return false;
for(int i = 5; i * i <= x; i += 6)
{
if(x % i == 0 || x % (i + 2) == 0) return false;
}
return true;
}
If prime numbers need to be printed for a particular range or to determine whether a number is prime or not, the sieve of the eratosthenes algorithm is probably preferable as it is very efficient in terms of time complexity O( n * log2( log2(n) ) ), but the space complexity of this algorithm can cause an issue if the numbers are exceeding certain memory limit.
We can optimize this simpler algorithm which has a time complexity of O(n1/2) by introducing few additional checks based on this thoerem as shown in the above isprime code block.
Despite the fact that Sieve of Erathosthenes algorithm is efficient in terms of time complexity under space restrictions, the above provided isprime code block can be utilized, and there are numerous variations of the Sieve of Erathosthenes algorithm that perform considerably better, as explained in this link.
Many more algorithms exist, but in terms of solving coding challenges, this one is simpler and more convenient. You can learn more about them by clicking on the following links:
https://www.quora.com/Whats-the-best-algorithm-to-check-if-a-number-is-prime
https://www.baeldung.com/cs/prime-number-algorithms#:~:text=Most%20algorithms%20for%20finding%20prime,test%20or%20Miller%2DRabin%20method.
Your code will give a wrong answer if n is 1.
Your time complexity can be decreased to sqrt(n) , where n is the number.
Here is the code
bool isPrime(long int n)
{
if (n == 1)
{
return false;
}
int i = 2;
while (i*i <= n)
{
if (n % i == 0)
{
return false;
}
i += 1;
}
return true;
}
The "long int" will help to avoid overflow.
Hope this helps. :-)
If the numbers are not too big you could also try to solve this using the sieve of Eratosthenes:
#include <iostream>
#include <array>
using namespace std;
constexpr int LIMIT = 100001;
// not_prime because global variables are initialized with 0
bool not_prime[LIMIT];
void sieve() {
int i, j;
not_prime[2] = false;
for(int i = 2; i < LIMIT; ++i)
if(!not_prime[i])
for(int j = i + i; j < LIMIT; j += i)
not_prime[j] = true;
}
int existaP(int a[], int li, int ls){
if(li==ls)
if(!not_prime[a[li]] == true)
return 1;
else
return 0;
else
return existaP(a, li, (li + ls) / 2) + existaP(a, (li + ls) / 2 + 1, ls);
}
int main(){
int n, a[10001];
cin >> n;
for(int i = 1; i<=n; ++i) cin >> a[i];
sieve();
if(existaP(a,1,n) >= 1) cout << "Y";
else cout << "N";
return 0;
}
Basically when you encounter a prime all the numbers that are a multiple of it won't be primes.
P.S.: Acum am vazut ca esti roman :)
Poti sa te uiti aici pentru a optimiza si mai mult algoritmul: https://infoarena.ro/ciurul-lui-eratostene
Another inefficiency not yet mentioned is existaP(a, li, (li+ls)/2) + existaP(a, (li+ls)/2+1, ls);
In particular, the problem here is the +. If you know existaP(a, li, (li+ls)/2) > 0, then existaP(a, (li+ls)/2+1, ls) no longer matters. In other words, you're currently counting the exact number of unique factors, but as soon as you know a number has at least two factors you know it's not prime.
Here is one efficient way to check a given number is prime.
bool isprime(int n) {
if(n<=1)
return false;
if(n<=3)
return true;
if(n%2==0||n%3==0)
return false;
for(int i=5;i*i<=n;i=i+6) {
if(n%i==0||n%(i+2)==0)
return false;
}
return true;
}
This is a much faster algorithm in my opinion. It works on the Euclidean algorithm to calculate H.C.F. Basically, I check if the HCF of the number AND the consecutively second number is 1; and if the number itself is divisible by either 2 or 3. Don't ask how I mathematically reached the solution, it just struck me :D. The time complexity of this solution is O(log (max(a,b))), which is notably smaller than the time complexity of the program which runs a loop counter 2 to sqrt(n) is O(sqrt(n)).
#include <iostream>
using namespace std;
int hcf(int, int);
int hcf(int a, int b)
{
if (b == 0)
{
return a;
}
return hcf(b, a % b);
}
int main()
{
int a;
cout << "\nEnter a natural number: ";
cin >> a;
if(a<=0)
{
cout << "\nFor conventional reasons we keep the discussion of primes to natural numbers in this program:) (Read: Ring of Integers / Euclid's Lemma)";
return 0;
}
if (a == 1)
{
cout << "\nThe number is neither composite nor prime :D";
return 0;
}
if (a == 2)
{
cout << "\nThe number is the only even Prime :D";
return 0;
}
if (hcf(a, a + 2) == 1)
{
if (a % 2 != 0 && a % 3 != 0)
{
cout << "\nThe number is a Prime :D";
return 0;
}
}
cout << "\nThe number is not a Prime D:";
return 0;
}
Correct me if I'm wrong. I'm a student.
I am trying to implement this algorithm and I have having a hard time working out the algorithm to work for finding the prime numbers up to 1000. I don't really understand but my code is not giving me the correct output, if you can suggest a way I should change my code I would greatly appreciate it.
#include <iostream>
using namespace std;
bool isPrime(int n);
int main() {
int i;
for(i = 1; i <= 1000; i++){
if( isPrime(i)) cout << "This number " << i << " is a prime. " << endl;
}
}
bool isPrime(int n){
if(n <= 1){
return false;
}
if(n == 2){
return true;
}
for(int i = 2; i < n; i++){
if(n % i == 0){
return false;
}else{
return true;
}
}
}
Your decision inside the for loop inside isPrime() is wrong. This is a criterion to terminate the loop:
if(n % i == 0){
but the elsepart is no reason to terminate. You have to wait until the for loop finished. Like this:
for(int i = 2; i < n; i++){
if(n % i == 0){
// Here, we are sure that n can be divided by any other numbers than 1 and n.
return false;
}
}
// Here, we are sure that n cannot be divided by any number 2 .. (n-1).
return true;
}
By the way, you only have to check until the square root of n. You can spare the rest.
There is problem in your isPrime function
bool isPrime(int n){
if(n <= 1){
return false;
}
if(n == 2){
return true;
}
for(int i = 2; i < n; i++){
if(n % i == 0){
return false;
}
else{
return true; /* this line is very dangerous. When there is odd number it is not divisible by two so the control goes to else block and you get every odd number as your prime number */
}
}
}
Instead use this
bool isPrime(int n){
if(n <= 1){
return false;
}
if(n == 2){
return true;
}
for(int i = 2; i < n; i++){
if(n % i == 0){
return false;
}
}
return true;
}
For Sieve Of Erastosthenes
try this code it may help
int b;
cout << "Enter upper limit" << endl;
cin >> b;
bool *x;
x = new bool[b];
x[2] = true;
for (int i = 2; i < b; i++)
{
int count = 2;
if (x[i])
{
cout << i << endl;
while (i*count < b)
{
x[i*count] = false;
count++;
}
}
}
The problem is in the isPrime function.
Your isPrime function says if the the first value of i (i.e 2) is not divided by n then return true. So for eg. 21, 27 etc are also counted as a prime number.
You can use a flag variable in the isPrime function and used it to determine whether the n is prime or not. Like this
boolean prime = true;
for(int counter = 2; counter <= number / 2; counter++) {
if(number % counter == 0) {
prime = false;
break;
}
}
return prime;
I don't think this is Sieve of Eratosthenes algorithm. If you want to implement this algorithm then you can read from here.
#include <iostream>
using namespace std;
int main(){
int ctr = 0;
int count = 1; //Counts the nth prime number
int num = 3;
int div = 2; //Potential factors of the number
while(count <= 1000){
while(div < num){
if(num%div == 0){
ctr += 1; //If ctr is equal to 0, then num is prime
}
div += 1;
}
if(ctr == 0){ //If num is prime, count increases by 1
count += 1;
}
num += 1;
}
cout << num;
}
This is the code that I made to output the 1000th prime number. However, there must be something wrong with my program since it does not output 7919, which is the 1000th prime number.
It usually helps to refactor code like this into functions that have a clearly defined and testable behavior. For instance, the inner part of your code is a 'isPrime' function, and if you define it like this:
bool isPrime(int n) {
int div = 2; //Potential factors of the number
while (div < n) {
if (n % div == 0) {
return false;
}
++div;
}
return div == n;
}
It is easy to test, either through unit testing, or just manually checking if isPrime() works ok.
That makes the rest of the code more easy to write (and more importantly, read):
int primeCount = 0;
int n = 1;
while (primeCount < 1000) {
if (isPrime(n++)) {
++primeCount;
}
}
--n;
std::cout << n << std::endl;
As for why your code doesn't work. You should debug it. Go through line by line and see where it deviates from your expectations. Start out with finding the 3rd prime number, and not the 1000th.
Your isPrime part does not do what it is supposed to. Finding out why isn't hard, and you should definitely do that as a debugging-exercise, and not go with an easy answer from stackoverflow.
#include <stdio.h>
int main(){
int ctr = 0;
int count = 1; //Counts the nth prime number
int num = 3;
int div = 2; //Potential factors of the number
while(count <= 1000){
while(div < num){
if(num%div == 0){
ctr += 1; //If ctr is equal to 0, then num is prime
}
div += 1;
}
if(ctr == 0){ //If num is prime, count increases by 1
count += 1;
}
num += 1;
ctr=0;
div=2;
}
printf("%d",num);
}
#include<stdio.h>
main()
{
int n;
int a,b,flag=1;
scanf("%d",&n);
for(a=2; a<=n; a++)
{
if(n % a == 0)
{
printf("not prime");
flag = 0;
break;
}
}
if(flag == 1)
{
printf("is prime");
}
getch();
}
when you use this for loop
for(a=2; a<=n; a++)
when user will input 2 it will print "not prime:
if you put that if(flag == 1) statement inside the for loop it doesn't print anything when the user inputs 2. Why is that if(flag == 1) outside that for loop
#include<stdio.h>
main()
{
int i, num, flag = 1;
scanf("%d",&num);
for(i=2; i<=sqrt(num); i++)
{
if(num%i==0)
{
printf("not prime");
flag=0;
break;
}
}
if(flag==1)
{
printf("is prime");
}
getch();
}
when you will use square root in for loop
for(i=2; i<=sqrt(num); i++)
then it give correct result
if you enter 2 then it prints 2 is prime number
WHY ?
and what is flag variable how does it work ?
The problem is that this line is wrong:
for(a=2; a<=n; a++)
It should be this:
for(a=2; a<n; a++)
Because n is always divisible by itself it will mean that n % a == 0 when a is n. This does not mean the number is not prime. A prime is exactly divisible by 1 and itself, but no other integer.
When you change the test to a <= sqrt(num) you also happen to fix this bug.
for(a=2; a <= n; a++)
should be
for(a=2; a < n; a++)
//^ difference
Also, when you use sqrt(n), you better write this outside the loop to improve performance:
int m = sqrt(n); //store the result in int type
for(a=2; a <= m ; a++)
In this way, you calculate sqrt(n) just ONCE, instead of in every iteration, and instead of relying on the compiler to optimize this step.