Check whether a number is a sum of two prime numbers - java

The problem is to check a random number n can be the sum of 2 random prime numbers. For example,
if n=34 the possibilities can be (3+31), (5+29), (17+17)...
So far I have managed to save prime numbers to the array, but have no clue how I could check, if n is the sum of 2 prime numbers.
This is part of my code:
public static void primeNumbers(int n) {
int i = 0, candidate = 2, countArray = 0, countPrime = 0;
boolean flag = true;
while (candidate <= n) {
flag = true;
for (i = 2; i < candidate; i++) {
if ((candidate % i) == 0) {
flag = false;
break;
}
}
if (flag) {
countPrime++;
}
candidate++;
}
int[] primeNumbers = new int[countPrime];
while (candidate <= n) {
flag = true;
for (i = 2; i < candidate; i++) {
if ((candidate % i) == 0) {
flag = false;
break;
}
}
if (flag) {
primeNumbers[countArray] = candidate;
}
candidate++;
countArray++;
}
for (i = 0; i <= primeNumbers.length; i++) {
}
}
First I counted how many prime numbers are between 1-n so I can declare and initialize my array for prime numbers. Then I save prime numbers to the array. But now I have no idea how I could check if n is the sum of 2 prime numbers.

Given that you already have list of "prime numbers less than the given number", It is a very easy task to check if two prime numbers can sum to given number.
for(int i=0; i<array.length; i++){
int firstNum = array[i];
int secondNum = givenNum - firstNum;
/* Now if it is possible to sum up two prime nums to result into given num, secondNum should also be prime and be inside array */
if(ArrayUtils.contains(array, secondNum)){
System.out.println("Yes, it is possible. Numbers are "+ firstNum + " and " + secondNum);
}
}
EDIT: ArrayUtils is part of Apache Commons Lang library
You can however use ArrayList instead to use contains method.

You do not have to check all prime numbers from 1 to the given number or you don't even need an array.
Algorithm one can be;
First of all write a function that checks whether a given number is prime.
Split the number into two parts, 0 and the remaining value(the number itself). Now start decreasing the number part by 1 and start adding 1 to 0 simultaneously. Stop when the number part which we are decreasing becomes 0 or both the parts are prime numbers.
Another algorithm can be like this;(It is similar to the accepted answer)
Start subtracting prime numbers from the given number starting from 2.Check whether the subtraction is also prime.
The time you get the subtraction as a prime number, stop , you have got the two prime numbers that sum up to the given number.

Related

What would be the solution for this question if it had strong test cases?

https://www.codechef.com/problems/PRIME1
If you don't wish to open the link here's a short description of the question below :
This problem asks us to print all prime number within a given range.
There are 10 test cases and each one will provide us a start and end value of a range.
The start and end of this range can take values between 1 and 10^9.
The difference between the start and end values is 10^5 or lesser.
The time limit for the problem is 2 seconds. (that is, for all 10 test cases together)
My thinking on this:
A common estimate is that the online judge used by Codechef can perform ~10^7 operations in 1 second.
We have 10 test cases and in the worst case each one will have a range of 10^5 (since that's the max range given). Now,
10*(10^5)= 10^6 , which is the max number of operations we can perform in 1 second, so for each number in the range we must identify if it is prime in O(1).
Approaches:
1. Simple method for testing primality - Iterate through all numbers from 2 to n-1 and for every number check if it divides n
Ans: Won't work because for the worst case,
= (numbers of the highest size) * (total numbers in max range) * (total test cases)
= (10^9 * 10^5) * 10
= 10^15
2. Square root method to check if prime
Ans: Won't work because, in the worst case,
= (calculating sq. root of numbers of size 10^9) * (total numbers in max range) * (total test cases)
= (~10^4) * (10^5) * 10
= 10^10
3. Using Sieve of Eratosthenes
Precompute primes from 1 to 32000 (this number because it is approx the sq. root of 10^9)
Then to check of a value within the range is primeor not-
if value is between 1 and 32000
directly refer the precomputed value
else
try dividing that value by all precomputed primes, if it divides evenly then its not a prime
Ans: won't work because, in the worst case,
= (number of primes between 1 and 32000) *(total numbers in max range) * (total test cases)
= (3234) * (10^5) * (10)
= 10^9
Code for approach 3:
import java.util.*;
import java.io.*;
class Main
{
static ArrayList<Integer> sieve(ArrayList<Integer> primes)
{
int[] prime=new int[32001];
for(int i=2; i<32001; i++)
{
if(prime[i]==0)
{
for(int j=i+i; j<32001; j+=i)
{
prime[j]=1;
}
}
}
for(int i=2; i<32001; i++)
{
if(prime[i]==0)
{
primes.add(i);
}
}
return primes;
}
public static void main(String[] args)
{
int t,m,n,flag;
ArrayList<Integer> primes= new ArrayList<Integer>();
FastReader scanner= new FastReader();
t=scanner.nextInt();
primes= sieve(primes);
while(t-- > 0)
{
m=scanner.nextInt();
n=scanner.nextInt();
for(int i=m; i<=n; i++)
{
if(i < 32001)
{
if(primes.contains(i))
{
System.out.println(i);
}
}
else
{
flag=0;
for(int j=0; j<primes.size(); j++)
{
if(i%primes.get(j) == 0)
{
flag=1;
break;
}
}
if(flag==0)
{
System.out.println(i);
}
}
}
System.out.println();
}
}
}
While approach 1 obviously didn't work, approach 2 and 3 surprisingly passed!
I'm guessing it passed because the test cases for the problem were weak.
A strong test case would be something like:
10
999900000 1000000000
999899999 999999999
999899998 999999998
999899997 999999997
999899996 999999996
999899995 999999995
999899994 999999994
999899993 999999993
999899992 999999992
999899991 999999991
I ran approach 3 for this test case and it is always taking more than 2 seconds to compute.
If this question did have strong test cases, what would be the correct approach to solve it with the given constraints?
If you going to try figure out prime numbers in a range use the Sieve of Eratosthene algorithm. The basic premise of Sieve is that give a range of numbers you eliminate all numbers that are multiples of prime factors (i.e once we establish that 2 is prime, we eliminate all its multiples ...4, 6, 8, etc)
A implementation of this would be as follows:
private void printPrimes(int max) {
int [] prime = new int[max + 1];
for (int i = 1; i <= max; i++) {
prime[i] = i; // Assume everything is prime initially
}
// if number is prime, then multiples of that factor are not prime
for (int f = 2; f * f <= max; f++) {
if (prime[f] != 0) {
for (int j = f; f * j <= max; j++) {
prime[f * j] = 0;
}
}
}
int counter = 0;
for (int i = 1; i <= max; i++) {
if (prime[i] != 0) counter++;
}
prime = Arrays.stream(prime).filter(i -> i != 0).toArray();
System.out.println("There are " + counter + " primes between 1 and " + max);
System.out.println(Arrays.toString(prime));
}

How to determine if a number is prime

Okay my issue is less of how to figure out if a number is prime, because I think I figured that out, but more of how to get it to display properly.
Here's my code:
public static void main(String[] args) {
// Declare Variables
int randomNumbers = 0;
int sum = 0;
//Loop for number generation and print out numbers
System.out.print("The five random numbers are: ");
for (int i = 0; i <= 4; i++)
{
randomNumbers = (int)(Math.random()*20);
sum += randomNumbers;
if (i == 4) {
System.out.println("and " + randomNumbers + ".");
}
else {
System.out.print(randomNumbers + ", ");
}
}
//Display Sum
System.out.println("\nThe sum of these five numbers is " + sum + ".\n");
//Determine if the sum is prime and display results
for(int p = 2; p < sum; p++) {
if(sum % p == 0)
System.out.println("The sum is not a prime number.");
else
System.out.println("The sum is a prime number.");
break;
}
}
}
Now my problem is, if the number ends up being something like 9, it'll say it is a prime number, which it is not. I think the issue is that the break is stopping it after one loop so it's not incrementing variable p so it's only testing dividing by 2 (I think). But if I remove the break point it will print out "The sum is/is not a prime number" on every pass until it exits the loop. Not sure what to do here.
Your method for finding if your number is prime is the correct method.
To make it so that it does not consistently print out whether or not the number is prime, you could have an external variable, which represents whether or not the number is prime.
Such as
boolean prime = true;
for (int p = 2; p < sum; p++) {
if (sum % p == 0) {
prime = false;
break;
}
}
if (prime)
System.out.println("The sum is a prime number.");
else
System.out.println("The sum is not a prime number.");
By doing this method the program will assume the number is prime until it proves that wrong. So when it finds it is not prime it sets the variable to false and breaks out of the loop.
Then after the loop finishes you just have to print whether or not the number was prime.
A way that you could make this loop faster is to go from when p = 2 to when p = the square root of sum. So using this method your for loop will look like this:
double sq = Math.sqrt((double)sum);
for (int p = 2; p < sq; p++) {
//Rest of code goes here
}
Hope this helps
You need to store whether or not the number is prime in a boolean outside of the loop:
//Determine if the sum is prime and display results
boolean isPrime = true;
for(int p = 2; p < sum; p++) {
if(sum % p == 0){
isPrime = false;
break;
}
}
if(isPrime){
System.out.println("The sum is a prime number.");
} else {
System.out.println("The sum is not a prime number.");
}
You are right, currently your code tests dividing by two, and the break command is stopping after one loop.
After the first go of your loop (p==2), the break will always stop the loop.
The fastest fix to your code will change the loop part like this:
boolean isPrime=true;
for(int p = 2; p < sum; p++) {
if(sum % p == 0) {
isPrime=false;
System.out.println("The sum is not a prime number.");
break;
}
}
if (isPrime)
System.out.println("The sum is a prime number.");
This code can be improved for efficiency and for code elegance.
For efficiency, you don't need to check divisibility by all numbers smaller than sum, it's enough to check all numbers smaller by square-root of sum.
For better code, create a seperate function to test if a number is prime.
Here is an example that implements both.
// tests if n is prime
public static boolean isPrime(int n) {
if (n<2) return false;
for(int p = 2; p < Math.sqrt(n); p++) {
if(n % p == 0) return false; // enough to find one devisor to show n is not a prime
}
return true; // no factors smaller than sqrt(n) were found
}
public static void main(String []args){
...
System.out.println("sum is "+ sum);
if (isPrime(sum))
System.out.println("The sum is a prime number.");
else
System.out.println("The sum is not a prime number.");
}
Small prime numbers
Use Apache Commons Math primality test, method is related to prime numbers in the range of int. You can find source code on GitHub.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
// org.apache.commons.math3.primes.Primes
Primes.isPrime(2147483629);
It uses the Miller-Rabin probabilistic test in such a way that a
result is guaranteed: it uses the firsts prime numbers as successive
base (see Handbook of applied cryptography by Menezes, table 4.1 / page 140).
Big prime numbers
If you are looking for primes larger than Integer.MAX_VALUE:
Use BigInteger#isProbablePrime(int certainty) to pre-verify the prime candidate
Returns true if this BigInteger is probably prime, false if it's
definitely composite. If certainty is ≤ 0, true is returned.
Parameters: certainty - a measure of the uncertainty that the caller
is willing to tolerate: if the call returns true the probability that
this BigInteger is prime exceeds (1 - 1/2certainty). The execution
time of this method is proportional to the value of this parameter.
Next use "AKS Primality Test" to check whether the candidate is indeed prime.
So many answers have been posted so far which are correct but none of them is optimized. That's why I thought to share the optimized code to determine prime number here with you. Please have a look at below code snippet...
private static boolean isPrime(int iNum) {
boolean bResult = true;
if (iNum <= 1 || iNum != 2 && iNum % 2 == 0) {
bResult = false;
} else {
int iSqrt = (int) Math.sqrt(iNum);
for (int i = 3; i < iSqrt; i += 2) {
if (iNum % i == 0) {
bResult = false;
break;
}
}
}
return bResult;
}
Benefits of above code-:
It'll work for negative numbers and 0 & 1 as well.
It'll run the for loop only for odd numbers.
It'll increment the for loop variable by 2 rather than 1.
It'll iterate the for loop only upto square root of number rather than upto number.
Explanation-:
I have mentioned the four points above which I'll explain one by one. Code must be appropriately written for the invalid inputs rather the only for valid input. Whatever answers have been written so far are restricted to valid range of input in which number iNum >=2.
We should be aware that only odd numbers can be prime, Note-: 2 is the only one even prime. So we must not run for loop for even numbers.
We must not run for loop for even values of it's variable i as we know that only even numbers can be devided by even number. I have already mentioned in the above point that only odd numbers can be prime except 2 as even. So no need to run code inside for loop for even values of variable i in for.
We should iterate for loop only upto square root of number rather than upto number. Few of the answers has implemented this point but still I thought to mention it here.
With most efficient time Complexity ie O(sqrt(n)) :
public static boolean isPrime(int num) {
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
you can use the Java BigInteger class' isProbablePrime method to determine and print whether the sum is prime or not prime in an easy way.
BigInteger number = new BigInteger(sum);
if(number.isProbablePrime(1)){
System.out.println("prime");
}
else{
System.out.println("not prime");
}
You can read more about this method here https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html#isProbablePrime%28int%29

Difference of implementation and mathematical proof of efficient algorithm for finding prime numbers

When i study from Introduction to Java programming book of Liang, i am stuck at a point. The problem is to find prime numbers efficiently.
In order to find whether n is prime or not, we must check whether n is divisible by numbers 2,3,4,...,sqrt(n) .
We can make this algorithm more efficient by checking whether n is divisible by numbers 2,3,4,...,floor(sqrt(n)).
For example, numbers between 36 and 48, their (int)(Math.sqrt(number)) is 6. But, according to the below program, for number=40, squareRoot is 7, not 6. Namely, according to the mathematical proof, we check whether 40 is prime by checking 40 is divisible by 2,3,4,5,6.
According to the below program, we check whether 40 is prime by checking 40 is divisible by 2,3,4,5,6,7. This the contradiction. I don't understand it. Help please.
Here is the algorithm implementing this problem :
import java.util.Scanner;
public class EfficientPrimeNumbers {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Find all prime numbers <= n, enter n: ");
int n = input.nextInt();
// A list to hold prime numbers
java.util.List<Integer> list =
new java.util.ArrayList<Integer>();
final int NUMBER_PER_LINE = 10; // Display 10 per line
int count = 0; // Count the number of prime numbers
int number = 2; // A number to be tested for primeness
int squareRoot = 1; // Check whether number <= squareRoot
System.out.println("The prime numbers are \n");
// Repeatedly find prime numbers
while (number <= n) {
// Assume the number is prime
boolean isPrime = true; // Is the current number prime?
if (squareRoot * squareRoot < number) squareRoot++;
// For numbers between 36 and 48, squareRoot is 7 which contradicts with the matematical proof.!!!
// ClosestPair if number is prime
for (int k = 0; k < list.size()
&& list.get(k) <= squareRoot; k++) {
if (number % list.get(k) == 0) { // If true, not prime
isPrime = false; // Set isPrime to false
break; // Exit the for loop
}
}
// Print the prime number and increase the count
if (isPrime) {
count++; // Increase the count
list.add(number); // Add a new prime to the list
if (count % NUMBER_PER_LINE == 0) {
// Print the number and advance to the new line
System.out.println(number);
}
else
System.out.print(number + " ");
}
// Check if the next number is prime
number++;
}
System.out.println("\n" + count +
" prime(s) less than or equal to " + n);
}
}
The program only checks for divisibility by primes lower than or equal to sqrt(number) + 1. Once a prime number is detected, it gets added to your list object:
if (isPrime) {
count++; // Increase the count
list.add(number); // Add a new prime to the list
Here is where you check for divisibility by numbers in this list:
for (int k = 0; k < list.size() && list.get(k) <= squareRoot; k++) {
if (number % list.get(k) == 0) { // If true, not prime
So for numbers between 36 and 48, it checks 2, 3, 5, 7, which is actually better than 2, 3, 4, 5, 6. Asymptotically, they're still the same, but in practice, you save some work by only checking for divisibility against the primes.
In fact you can save an operation and change the <= in list.get(k) <= squareRoot to <, for the reasons you describe. Then it won't even bother with 7 for numbers between 36 and 48, and it will be closer to the theory you have.

Prime Number Calculations Help Java

I am a novice, please excuse my lack of organization.
Okay, so what I did was I made an array filled with all the prime numbers between 8 and 100. What I want to do now is make another array that finds all the prime numbers between 101-200. So allow me to explain how I did the first part:
//Prime1 is an dynamic integer array which stores all the prime numbers between 8 and 100
int arrayCounter = 0;
for(int primeTest = 8; primeTest<=100; primeTest++)
{
if(primeTest%2!=0 && primeTest%3!=0 && primeTest%5!=0 && primeTest%7!=0)
{
Prime1.add(primeTest); //adds the prime numbers to array
arrayCounter = arrayCounter +1;
}
else
{
arrayCounter = arrayCounter + 1;
}
}
Now back to the main issue, rather than writing "if(primeTest % "prime#" !=0)" I would like to be able to use modulus through the entire Prime1 array and see if all the values do not equal zero... Let me elaborate.
for(int primeTest2 = 101; primeTest2 <= 200; primeTest2++)
{
for(int arrayCounter2 = 0; arrayCounter2 < Prime1.size(); arrayCounter2++)
{
if(primeTest2 % Prime1.get(arrayCounter2) != 0 )
{
Prime2.add(primeTest2);
}
}
}
//please forgive any missing braces
^^So what happens here is that I take a value starting at 101 and modulus it with the first value of the Prime1 array. As you know, this may give me a false positive because 11 (the first prime number in the array) may still show true even with numbers which are not prime. This is why I need to be able to test a number with all the values in the array to ensure that it cannot be divided by any other prime number (meaning that it is prime).
Your method is extremely inefficient, nevertheless, here is how you can fix it:
for (int primeTest2 = 101; primeTest2 <= 200; primeTest2++)
{
boolean prime = true;
for (int arrayCounter2 = 0; arrayCounter2 < Prime1.size(); arrayCounter2++)
{
if (primeTest2 % Prime1.get(arrayCounter2) == 0)
{
prime = false;
break;
}
}
if (prime)
Prime2.add(primeTest2);
}
BTW, for the first set of prime numbers, it is sufficient to use 2, 3, 5, 7, 11, 13.
Take a boolean and set it to true. If the number can be divided by any of your primes from 8 to 100 without a remainder, than set it to false. If it is still true after testing every number, add the tested number to the Prime2 array, otherwise continue with the next number. Example:
for(int n = 101; n <= 200; n++)
{
boolean isPrime = true;
for(Integer p : Prime1)
if(n % p == 0 )
{
isPrime = false;
break;
}
if(isPrime)
Prime2.add(n);
}
But there are better alorithms out there to check if a number is prime or to calculate alle primes below n. For example the Sieve of Eratosthenes.

Print every prime number before N number

Hey I am beginning to program using java and my teacher used this example in class for our homework which was to create a java program that prints out every prime number before reaching the upper limit that the user inputs. I am not understanding the second part and wondering if someone could help explaining it to me.
import java.util.Scanner;
public class Primes {
public static void main(String args[]) {
//get input for the upper limit
System.out.println("Enter the upper limit: ");
//read in the limit
int limit = new Scanner(System.in).nextInt();
//use for loop and isPrime method to loop through until the number reaches the limit
for(int number = 2; number<=limit; number++){
//print prime numbers only before the limit
if(isPrime(number)){
System.out.print(number + ", ");
}
}
}
//this part of the program determines whether or not the number is prime by using the modulus
public static boolean isPrime(int number){
for(int i=2; i<number; i++){
if(number%i == 0){
return false; //number is divisible so its not prime
}
}
return true; //number is prime now
}
}
I guess that what you mean by second part is the isPrime method.
What he is doing is using '%' operator which returns the integer remainder of the division between 'number' and 'i'. As a prime number is just divisor for itself and the number 1, if the remainder is 0 it means is not a prime number. Your teacher is looping with the 'i' variable until the limit number and checking if any of the numbers is prime by looking the result of the % operation.
Hope this is helpful for you!!
In the second part
if(number%i == 0)
% usually gives you a remainder if there is.
eg
5 % 2 gives 1
4 % 2 gives 0
for(int i=2; i<number; i++)
Here you are looping through from 2 to the number. Since all numbers are divisible by 1 you start from 2.
Also you stop before number (number -1) since you dont want to check if the number is divisible by itself (because it is).
If a number is divisible by any other number other than 1 and itself (number from 2 to number -1) then it is not a prime number.
Just a short (not efficient) reference for finding prime numbers if you need it:
int upperLimit = 30; //Set your upper limit here
System.out.println(2);
for(int i = 2; i < upperLimit; i++)
for(int j = 2; j < i; j++)
if(i % j == 0 && i != 2)
break;
else if(j == i - 1)
System.out.println(i);

Categories