In order to solve a question I have to generate a list of prime numbers from 1 to 3000000, so I tried several ways to do this and unfortunately all failed...
First try: because all prime numbers bigger than 2 are odd numbers, so I first generate a list of odd numbers started with 3 called allOddNums. And then I generate a list of all composite numbers called allComposite. Then I remove all the number in allComposite from allOddNums to obtain prime numbers. Here is my code:
/** Prime Numbers Generation
* Tony
*/
import java.util.*;
public class PrimeNumG {
public static void main(String[] args) {
List <Long> allOddNums = new ArrayList<Long>();
for (long i = 3; i < 200; i += 2) {
allOddNums.add(i);
}
// composite number generator:
List <Long> allComposite = new ArrayList<Long>();
for (long a = 2; a < Math.round(Math.sqrt(3000000)); a += 2) {
for (long b = 2; b < Math.round(Math.sqrt(3000000)); b += 2) {
allComposite.add(a*b);
}
}
// remove duplicated:
Set <Long> hs = new HashSet<Long>();
hs.addAll(allComposite);
allComposite.clear();
allComposite.addAll(hs);
// remove all composite from allRealNums = allPrime
allOddNums.removeAll(allComposite);
allOddNums.add(0, (long)2);
System.out.printf("%s ", allOddNums);
Scanner sc = new Scanner(System.in);
int times = sc.nextInt();
for (int i = 0; i < times; i++) {
int index = sc.nextInt();
System.out.print(allOddNums.get(index) + " ");
}
}
}
In this case, when I need to generate a few prime numbers it works fine. However, if I want to generate until 3000000 it fails me(used up memory).
Second try: I searched online and find an algorithm called sieve of Eratosthenes. then I first generate 2, 3, 5, 7, 9...(all odd numbers + 2), then I remove every 3rd number after 3 and every 5th number after 5. The code is as below:
/** Prime Number Generator
* Tony
*/
import java.util.*;
public class Solution61 {
public static void main(String[] args) {
List<Long> l1 = new ArrayList<Long> ();
// l1 generator: 3 5 7 9 11 ...
for (long d = 3; d < 100; d += 2) {
l1.add(d);
}
l1.add(1, (long)2); // 2 3 5 ...
removeThird(l1); // rm 3rd after 3
removeFifth(l1); // rm 5th after 5, now the l1 will be prime number
Scanner sc = new Scanner(System.in);
int times = sc.nextInt();
for (int i = 0; i < times; i++) {
int index = sc.nextInt();
System.out.print(l1.get(index) + " ");
}
}
/** removeThird : remove every 3rd number after 3
* param List | return void
*/
private static void removeThird(List<Long> l) {
int i = 1;
int count = 0;
while (true) {
if (count == 3) {
l.remove(i);
count = 1;
}
i ++;
count ++;
if (i > l.size()) {
break;
}
}
}
/** removeThird : remove every 5th number after 5
* param List | return void
*/
private static void removeFifth(List<Long> l) {
int i = 2;
int count = 0;
while (true) {
if (count == 5) {
l.remove(i);
count = 1;
}
i ++;
count ++;
if (i > l.size()) {
break;
}
}
}
}
This is still not up to the task because it also runs out of memory.
3rd try:
I tried to generate from 1 to the 3000000, and then remove every number is the product of prime number and another number. The code is as below:
/** print all the prime numbers less than N
* Tony
*/
public class primeGenerator {
public static void main(String[] args) {
int n = 3000000;
boolean[] isPrime = new boolean[n];
isPrime[0] = false; // because 1 is not a prime number
for (int i = 1; i < n; i++) {
isPrime[i] = true;
} // we set 2,3,4,5,6...to true
// the real number is always (the index of boolean + 1)
for (int i = 2; i <= n; i++) {
if (isPrime[i-1]) {
System.out.println(i);
for (int j = i * i; j < n; j += i /* because j is determined by i, so the third parameter doesn't mater*/) {
isPrime[j-1] = false;
}
}
}
}
}
it still fails me, well guess 3000000 is really a big number huh? Is there any simple and brilliant rookie-friendly way to generate prime numbers below 3000000? Thx!
fourth try:
#jsheeran Is this code below what your answer means? when I hit 1093 it gets slower and slower and my IDE still crashed. Plz tell me if I misinterprete your approach, thx!
/** new approach to find prime numbers
* Tony
*/
import java.util.*;
public class PrimeG {
/** isPrime
* To determine whether a number is prime by dividing the candidate number by each prime in that list
*/
static List<Long> primes = new ArrayList<Long> ();
private static void isPrime(long n) {
boolean condition = true;
for (int i = 0; i < primes.size(); i++) {
if (n % primes.get(i) == 0) {
condition = condition && false;
}
}
if (condition) {
findNextPrime(n);
}
}
/** findNextPrime
* expand the list of prime numbers
*/
private static void findNextPrime(long n) {
primes.add(n);
}
public static void main(String[] args) {
primes.add((long)2);
primes.add((long)3);
primes.add((long)5);
primes.add((long)7);
for (int i = 8; i < 3000000; i++) {
isPrime(i);
System.out.printf("%s", primes);
}
}
}
Fixed implementation of Sieve of Eratosthenes (your third try). I believe it should satisfy your needs.
public static void main (String[] args) throws java.lang.Exception {
int n = 3000000;
boolean[] isPrime = new boolean[n+1];
for (int i = 2; i <= n; i++) {
isPrime[i] = true;
}
for (int factor = 2; factor*factor <= n; factor++) {
if (isPrime[factor]) {
for (int j = factor; factor*j <= n; j++) {
isPrime[factor*j] = false;
}
}
}
for (int i = 2; i <= n; i++) {
if (isPrime[i]) System.out.println(i);
}
}
An alternative approach would be to begin with a list of primes consisting of 2 and 3. Have a method isPrime(int) to determine whether a number is prime by dividing the candidate number by each prime in that list. Define another method, findNextPrime(), which isPrime() can call to expand the list as needed. This approach has far lower overhead than maintaining lists of all odd and composite numbers.
Memory is not an issue in your case. Array of size n = 3000000 can be defined inside the stack frame of a function. Actually array of size 10^8 can be defined safely inside a function. If you need more than that define it as a gloabal variable(Instance variable). Coming to your code there is an IndexOutOfBoundsException in your third code. You need to check for factors of a number only uptill sqrt(n). Factors exist in pairs one factor <=sqrt(n) and other >=sqrt(n). So you can optimize the sieve of Eratosthenes algorithm. Here is a link to one wonderful tutorial on various optimizations of sieve.
This can generate prime numbers up to Integer.MAX_VALUE in few milliseconds. It also doesn't take as much memory as in Sieve of Eratosthenes approach.
public class Prime {
public static IntStream generate(int limit) {
return IntStream.range(2, Integer.MAX_VALUE).filter(Prime::isPrime).limit(limit);
}
private static boolean isPrime(int n) {
return IntStream.rangeClosed(2, (int) Math.sqrt(n)).noneMatch(i -> n % i == 0);
}
}
Related
Given a range of [1, 1000000000] we need to find prime numbers and all the digits of the prime number must be odd. (Example: 23 is not okay, 31 is okay)
If we go on by looping through each number and checking if it is prime etc, it is very slow. Is there a way to make this close to O(N) ?
I tried to eliminate as much as possible by looking at digits first. But after eliminating numbers with even digits the prime test is too slow.
for all numbers in [1, N]
check all digits, if any even digit, continue
check primality (this step is very slow)
And the primality test should not be very complex (probabilistic etc. is not possible, it must be possible to implement in a few minutes). The one I use is:
private static boolean isPrime(int n) {
boolean isPrime = true;
for (int divisor = 2; divisor <= n / 2; divisor++) {
if (n % divisor == 0) {
isPrime = false;
break;
}
}
return isPrime;
}
Maybe there is a trick to ensure a quick primality test but I couldn't find. Any suggestions? Thanks for reading.
You don't need to check all milliard numbers. Generate all numbers with only odd digits - there are at most 5^9~2 millions of them. Exclude those ending with 5 and not generate numbers divisible by 3 (in the moment of the last digit generation)
Then check these numbers for primality. Note that loop limit might be sqrt(n)
Ideone
class Ideone
{
static int oddcnt;
public static void checkprime(int x) {
for (int i=3; i <= Math.sqrt(x); i +=2)
if ((x % i) == 0)
return;
oddcnt++;
}
public static void genodd(int x, int curlen, int maxlen) {
x *= 10;
for (int i=1; i<10; i+=2) {
int nx = x + i;
checkprime(nx);
if (curlen < maxlen)
genodd(nx, curlen + 1, maxlen);
}
}
public static void main (String[] args) throws java.lang.Exception
{
genodd(0, 1, 8);
System.out.println(oddcnt);
}
}
The best way I can think of is to run a Prime Sieve of Eratosthenes to find all the primes in the range (0; sqrt(1000000000)) - which is around (0, 31622) - and time complexity O(n*log(log(n))) where n=31622. We will need those prime for a faster primality test.
Then, just loop through each number with odd digits - there are 5^10 = 9765625 ~ 10000000 such numbers. You saved 1000 times compared to iterating through all number in the original range.
The primality test using the primes we found in step 1 can be fast, as you only need to check with primes < sqrt(n), and you already have the primes. Even for the largest number in the range which is 999999999, the number of candidate primes is just 3432.
The following is a Java implementation
public class Execute {
private ArrayList<Long> primes = new ArrayList<>();
#org.junit.Test
public void findOddDecimalPrimes() {
primeSieve(32000);
System.out.println(primes.size());
for (int i = 0; i < 9765625; i++) {
String inBase5 = convertFromBaseToBase(i);
long evenDec = convertToOddDecimal(inBase5);
if (isPrime(evenDec)) {
System.out.println(evenDec);
}
}
}
private String convertFromBaseToBase(long i) {
return Long.toString(i, 5);
}
private long convertToOddDecimal(String str) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
s.append(1 + 2 * Integer.parseInt("" + str.charAt(i)));
}
return Long.parseLong(s.toString());
}
private boolean isPrime(long n) {
for (int i = 0; i < primes.size(); i++) {
if (primes.get(i) * primes.get(i) > n) break;
long divisor = n / primes.get(i);
if (divisor * primes.get(i) == n) return false;
}
return true;
}
/**
* References: www.geeksforgeeks.org
*/
private void primeSieve(int n)
{
// Create a boolean array "prime[0..n]" and initialize
// all entries it as true. A value in prime[i] will
// finally be false if i is Not a prime, else true.
boolean prime[] = new boolean[n+1];
for(int i=0;i<n;i++)
prime[i] = true;
for(int p = 2; p*p <=n; p++)
{
// If prime[p] is not changed, then it is a prime
if(prime[p] == true)
{
// Update all multiples of p
for(int i = p*p; i <= n; i += p)
prime[i] = false;
}
}
for (int i = 2; i < prime.length; i++) {
if (prime[i]) this.primes.add(Long.valueOf(i));
}
}
}
If your numbers are in order, you can optimize your isPrime function.
Here is a js sample version.
var primes = [];
function checkDigits(n) {
while(n > 1) {
var d = n % 10;
if ( d % 2 == 0) { return false; }
n = parseInt(n/10,10);
}
return true;
}
function isPrime(n) {
for(var i = 1; i < primes.length; i++) {
if(n % primes[i] == 0) {
return false;
}
}
var lastPrime = primes.length > 2 ? primes[primes.length - 1] : 1;
var inc = 2;
for(var i = lastPrime + inc; i < Math.sqrt(n); i += inc) {
if(n % i == 0) {
return false;
}
}
primes.push(n);
return true;
}
for(var i = 1; i < 100; i++) {
if(checkDigits(i) && isPrime(i)) {
console.log(i);
}
}
This is an open question in math and computer science in general.
In a nutshell no, there is no know way to solve that problem in O(1) to get your loop running in O(N) over the whole range.
If you solve that, dont tell anyone, and go get rich by breaking most of the encryptions today that use large prime numbers.
What you could do though, is make the loop over the devisor a bit smaller by useing sqrt(n).
That will bring that inner loop down from O(N^2) to O(sqrt(N))
And the whole complexity from O(N^2) to O(N*sqrt(N))=O(N^(3/2))
Anotger optimization would be to check the odd digits first beforre doing the complex Prime calculation
I have a program that is supposed to decrypt a number to its primes. The primes also have an order: for instance, 2 is the 1st prime number, 3 is the second 5 is the third and so on. The indexes are 1 is for a, two is for b, three is for c and so on. I don't know how to compare the two array lists in order to assign an index to each prime so I can decode a word which is encrypted in the number 72216017. The number 72216017 has the primes 17,19,47,67,71. If 2,3,5,7,11... are a,b,c,d,e... these five prime numbers make up the word ghost, I just don't know how to assign and sort these numbers by their index.
package name;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PrimeFactorsEffective {
private static int z;
private int w = z;
public static List<Integer> primeFactors(int numbers) {
int n = numbers;
List<Integer> factors = new ArrayList<Integer>();
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
if (n > 1) {
factors.add(n);
System.out.println(factors);
z = Collections.max(factors);
}
}
return factors;
}
public static void main(String[] args) {
System.out.println("Primefactors of 72216017");
for (Integer integer : primeFactors(72216017)) {
System.out.println(integer);
}
List<Integer> factors1 = new ArrayList<Integer>();
List<String> index1 = new ArrayList<String>();
int i;
int element = 0;
int num = 0;
int maxCheck = z; // maxCheck limit till which you want to find prime numbers
boolean isPrime = true;
String primeNumbersFound = "";
//Start loop 1 to maxCheck
for (i = 1; i <= maxCheck; i++) {
isPrime = CheckPrime(i);
if (isPrime) {
primeNumbersFound = primeNumbersFound + i + " ";
factors1.add(i);
factors1.get(num);
}
}
System.out.println("Prime numbers from 1 to " + maxCheck + " are:");
System.out.println(factors1);
}
public static boolean CheckPrime(int numberToCheck) {
int remainder;
for (int i = 2; i <= numberToCheck / 2; i++) {
remainder = numberToCheck % i;
if (remainder == 0) {
return false;
}
}
return true;
}
}
You can store the primes in a List (primes in this list will be in increasing order). Now you can use Collections.BinarySearch to get the index of the prime for which you wan to find the corresponding alphabet. Once you got the index (index here according to you starts from 1, so a's index is 1, b's index is 2, c's index is 3 and so on) you can do simply something like char currentCharacter = (char) ('a' + primeIndex - 1) and the variable currentCharacter will store the alphabet corresponding to primeIndex.
Some other minor things that I'd like to suggest:
Which checking whether a number is prime or not, you can simply check upto square-root of numberToCheck. So you can replace your loop for (int i = 2; i <= numberToCheck / 2; i++) to for (int i = 2; i*i <= numberToCheck; i++). Note that It is not a good idea to calculate square-root using Math.sqrt, instead you can have a condition like i*i <= numberToCheck.
Please refrain from naming your packages that seem to be random.
As of Java SE 7 explicit type-arguments while initializing the list are not required. You can replace List<Integer> factors1 = new ArrayList<Integer>() with List<Integer> factors1 = new ArrayList<>(). Please read this for more information.
Your factor method don't really look good to me, it don't give correct results. Please see the following method that gives correct result:
{{
public static List<Integer> primeFactors(int numbers) {
int n = numbers;
List<Integer> factors = new ArrayList<>();
for (int i = 2; n>1; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
z = Collections.max(factors);
return factors;
}
For an assignment I am doing for one of my classes, we have to implement a Sieve of Eratosthenes. I have tried seven times to get a code that works and have tried incorporating numerous solutions I've researched. I finally have one that will output numbers. Unfortunately, it prints both composite and prime numbers, and doesn't print 2.
My code is as follows:
public class EratosthenesSieveAttempt6 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int limit;
System.out.print("Please enter the highest number to check "
+ "(number must be greater than 2): ");
limit = keyboard.nextInt();
while (limit <= 2){
System.out.println("Error - number must be greater than 2.");
System.out.println("Please enter the highest number to check: ");
limit = keyboard.nextInt();
}
boolean[] numbers = new boolean[limit + 1];
int newPrime = 2;
for(int i = 0; i < limit + 1; i++){
numbers[i] = true;
}
for(int j = 1; j < limit + 1; j++) {
if (j % 2 == 0) {
numbers[j] = false;
}
for(int k = j + 1; k < limit + 1; k++) {
if(numbers[k] == true){
j = k;
System.out.println(k);
}
}
}
}
}
I'm suspecting that there is a problem with my loops. I fixed the i and j variables for my first two loops so that it would print out from 2 onward, the problem seems to be that it's not marking the composite numbers as false after I've initialized the array to true.
Thank you in advance for your help.
Here's an implementation of the Sieve of Eratosthenes I wrote the other day:
import java.util.BitSet;
public static BitSet composite(int max) {
BitSet composite = new BitSet(max);
max = composite.size();
for (int i = 4; i < max; i += 2) composite.set(i, true);
for (int i = 9; i < max; i += 6) composite.set(i, true);
int p = 5;
while (p*p < max) {
if (!composite.get(p)) {
for (int i = p*p; i < max; i += p*2) composite.set(i, true);
}
p += 2;
if (p*p >= max) break;
if (!composite.get(p)) {
for (int i = p*p; i < max; i += p*2) composite.set(i, true);
}
p += 4;
}
return composite;
}
Notes:
BitSet allocates 64-bit words, so the size may be larger than you requested (for example, if you ask it to go up to 1000, it will go up to 1024; that's the reason for max = composite.size() near the top)
Gets the 2's, 3's out of the way explicitly, and then
Relies on the fact that all primes larger than 3 are congruent to either 1 or 5 mod 6; this is the reason the final loop alternates between adding 2 and 4
It returns a BitSet that tells you which numbers are composite. One way to extract just the primes from it would be:
public static int[] primes(BitSet composite) {
int size = composite.size() - 2 - composite.cardinality();
int[] primes = new int[size];
int index = 0;
for (int i = 2; i < composite.size(); i++) {
if (!composite.get(i)) primes[index++] = i;
}
return primes;
}
This function its only working for certain numbers, but for 15, or 5 it does not give me correct next prime.
public static int nextPrime(int n) {
boolean isPrime = false;
int m = (int) Math.ceil(Math.sqrt(n));
int start = 3;
if (n % 2 == 0) {
n = n + 1;
}
while (!isPrime) {
isPrime = true;
for (int i = start; i <= m; i = i + 2) {
if (n % i == 0) {
isPrime = false;
break;
}
}
if (!isPrime) {
n = n + 2;
}
}
return n;
}
You don't need to go upto sqrt(n), you need to go upto sqrt(number) that you are evaluating
for example consider you pass n = 5
it will start loop from 3 and it will end the loop at 4 that is not what you need to find next prime number
outer loop
start from n + 1 until you find prime
inner loop
you should start from 3 and sqrt(numberUnderIteration)
You're setting your boundary at the square root of the original number only. In order for you to check if every next number works, you need to recalculate the boundary whenever the n value is changed. So, put int m = (int) Math.ceil(Math.sqrt(n)); inside of your while loop.
You also need to increment n by 1 before you start any calculations, or it will accept n itself as a prime number if it is one. For example, nextPrime(5) would return 5 because it passes the conditions.
And finally, you don't need to increment n by 2 at the end of your while loop because if you are on an even number, it will break out (keep adding 2 to an even number will always be even). I've commented the part of your code that I changed:
public static int nextPrime(int n) {
boolean isPrime = false;
int start = 2; // start at 2 and omit your if statement
while (!isPrime) {
// always incrememnt n at the beginning to check a new number
n += 1;
// redefine max boundary here
int m = (int) Math.ceil(Math.sqrt(n));
isPrime = true;
// increment i by 1, not 2 (you're skipping numbers...)
for (int i = start; i <= m; i++) {
if (n % i == 0) {
isPrime = false;
break;
}
}
// you don't need your "if (!isPrime)..." because you always increment
}
return n;
}
public static void main(String[] args) {
System.out.println(nextPrime(15)); // 17
System.out.println(nextPrime(5)); // 7
System.out.println(nextPrime(8)); // 11
}
You need to compute m inside the for loop.
while (!isPrime) {
isPrime = true;
int m = (int) Math.ceil(Math.sqrt(n));
// do other stuff
Your code works fine except when a prime number is given as input, your method returns input itself.
Example if 5 is your input nextPrime(5) returns 5. If you want 7 (next prime number after 5) to be returned in this case.
Just add n=n+1; at the start of your method. Hope this helps
Just for fun, I coded a quick Prime class that tracks known primes, giving a huge performance boost to finding multiple large primes.
import java.util.ArrayList;
public class Primes {
private static ArrayList<Integer> primes = new ArrayList<Integer>();
public static int nextPrime(int number){
//start it off with the basic primes
if(primes.size() == 0){
primes.add(2);
primes.add(3);
primes.add(5);
primes.add(7);
}
int idx = primes.size()-1;
int last = primes.get(idx);
//check if we already have the prime we are looking for
if(last > number){
//go to the correct prime and return it
boolean high = false;
boolean low = false;
int prevIdx = 0;
int spread = 0;
//keep finagling the index until we're not high or low
while((high = primes.get(idx-1) > number) || (low = primes.get(idx) <= number)){
spread = Math.abs(prevIdx-idx);
//because we always need to move by at least 1 or we will get stuck
spread = spread < 2 ? 2: spread;
prevIdx = idx;
if(high){
idx -= spread/2;
} else if(low){
idx += spread/2;
}
};
return primes.get(idx);
}
/*FIND OUR NEXT SERIES OF PRIMES*/
//just in case 'number' was prime
number++;
int newPrime = last;
//just keep adding primes until we find the right one
while((last = primes.get(primes.size()-1)) < number){
//here we find the next number
newPrime += 2;
//start with the assumption that we have a prime, then try to disprove that
boolean isPrime = true;
idx = 0;
int comparisonPrime;
int sqrt = (int) Math.sqrt(newPrime);
//make sure we haven't gone over the square root limit- also use post-increment so that we use the idx 0
while((comparisonPrime = primes.get(idx++)) <= sqrt){
if(newPrime % comparisonPrime == 0){
isPrime = false;
}
}
if(isPrime){
primes.add(newPrime);
}
}
return last;
}
}
And here is the test:
public class Test {
public static void main(String[] args){
long start;
long end;
int prime;
int number;
number = 1000000;
start = System.currentTimeMillis();
prime = Primes.nextPrime(number);
end = System.currentTimeMillis();
System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");
number = 500;
start = System.currentTimeMillis();
prime = Primes.nextPrime(number);
end = System.currentTimeMillis();
System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");
number = 1100000;
start = System.currentTimeMillis();
prime = Primes.nextPrime(number);
end = System.currentTimeMillis();
System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");
}
}
This results in the following output:
Prime after 1000000 is 1000003. Took 384 milliseconds.
Prime after 500 is 503. Took 10 milliseconds.
Prime after 1100000 is 1100009. Took 65 milliseconds.
As you can see, this takes a long time the first iteration, but we only have to perform that operation once. After that, our time is cut down to almost nothing for primes less than our first number (since it's just a lookup), and it is very fast for primes that are just a bit bigger than our first one (since we have already done most of the work).
EDIT: Updated search for existing primes using a variation on a Binary Search Algorithm. It cut the search time at least in half.
import java.util.Scanner;
class Testing
{
public static void main(String Ar[])
{
int a = 0, i, j;
Scanner in = new Scanner(System.in);
a = in.nextInt();
for (j = a + 1;; j++)
{
for (i = 2; i < j; i++)
{
if (j % i == 0)
break;
}
if (i == j)
{
System.out.println(j);
break;
}
}
}
}
Here is the perfect code for finding next prime for a given number.
public class NextPrime
{
int nextPrime(int x)
{
int num=x,j;
for( j=num+1;;j++)
{
int count=0;
for(int i=1;i<=j;i++)
{
if(j%i==0)
{
count++;
//System.out.println("entered");
}
//System.out.println(count);
}
if(count==2)
{
System.out.println(" next prime is ");
break;
}
}return j;
}
public static void main(String args[])
{
NextPrime np = new NextPrime();
int nxtprm = np.nextPrime(9);
System.out.println(nxtprm);
}
}
//I hope the following code works exactly.
import java.util.Scanner;
public class NextPrime {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a positive integer number : ");
int n = scanner.nextInt();
for (int x = n + 1;; x++) {
boolean isPrime = true;
for (int i = 2; i < x / 2; i++) {
if (x % i == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
System.out.println("Next prime is : " + x);
break;
}
}
}
}
I am attempting Problem 50 of project Euler.
The prime 41, can be written as the sum of six consecutive primes:
41 = 2 + 3 + 5 + 7 + 11 + 13 This is the longest sum of consecutive
primes that adds to a prime below one-hundred. The longest sum of
consecutive primes below one-thousand that adds to a prime, contains
21 terms, and is equal to 953. Which prime, below one-million, can be
written as the sum of the most consecutive primes?
Here is my code:
public class consPrime
{
static int checker(int ar[],int num,int index) //returns no.of consecutive
{ //primes for the given num
while(true)
{
int temp=num;
for(int i=index;i>=0;i--)
{
temp=temp-ar[i];
if(temp==0)
{
return (index-i+1);
}
}
index--;
if(index==0)
return 0;
}
}
public static void main(String args[])
{
int n=100000;
int ar[]=new int[n];
int total=0;int flag;
for(int i=2;i<1000000;i++) //Generates an array of primes below 1 million
{
flag=1;
for(int j=2;j<=Math.sqrt(i);j++)
{
if(i%j==0)
{
flag=0;
break;
}
}
if(flag==1)
{
ar[total]=i;
total++;
}
}
int m=0;
int Big=0;
for(int i=total;i>=0;i--) //Prints the current answer with no.of prime
{
m=checker(ar,ar[i],i-1);
if(Big<=m)
{Big=m;
System.out.println(ar[i]+" "+Big);
}
}
}
}
Basically it just creates a vector of all primes up to 1000000 and then loops through them finding the right answer. The answer is 997651 and the count is supposed to be 543 but my program outputs 990707 and 75175 respectively. What might be wrong?
Several big problems:
Some minor problem first: learn to proper indent your code, learn to use proper naming convention. In Java, variable names uses camelCasing while type name uses PascalCasing.
Lots of problems in your logics: you loop thru the prime number array, until you hit zero or until looped thru all numbers in the array. However, please be awared that, there is underflow/overflow for integer. It is possible that the "temp" keeps on deducts and become negative and become positive and so-on-and-so-forth and hit zero. However that's not the correct answer
You only tried to find the consecutive numbers that ends at index - 1. For example, to check for prime number at index 10, you are finding consecutive primes from index 9 backwards. However consecutive prime sum up to your target number rarely (in fact almost never, except for 5) contains the "previous" prime number. The whole logic is simply wrong.
Not to mention the incorrect parameters you passed for checker, which is mentioned by comment of user #pm-77-1
Here is another approach that takes 43 ms.
It is based on the following approach:
1) The primes <= 1000000 are generated using a sieve
2) It iterates in O(n2) through all numbers and it counts the consecutive primes. The first loop changes the first element of the sequence, the second one takes the elements starting from that position and adds them to a sum. If the sum is prime and it consists of the biggest number of primes, than it is kept in a variable.
import java.util.ArrayList;
import java.util.List;
public class P50 {
private final static int N = 1_000_000;
public static void main(String[] args) {
boolean primes[] = generatePrimes(N);
List<Integer> primeIntegers = new ArrayList<Integer>();
for (int i = 0; i < primes.length; i++) {
if (primes[i]) {
primeIntegers.add(i);
}
}
int count = 0;
int sum = 0;
int finalSum = 0;
int finalCount = 0;
int totalPrimes = primeIntegers.size();
for (int start = 0; start < totalPrimes; start++) {
sum = 0;
count = 0;
for (int current = start; current < totalPrimes; current++) {
int actual = primeIntegers.get(current);
sum += actual;
if ( sum >= N ) {
break;
}
if ( primes[sum] ) {
if ( count > finalCount ) {
finalCount = count;
finalSum = sum;
}
}
count++;
}
}
System.out.println(finalSum);
}
private static boolean[] generatePrimes(int n) {
boolean primes[] = new boolean[n];
for (int i = 0; i < n; i++) {
primes[i] = true;
}
primes[0] = false;
primes[1] = false;
// i = step
for (int i = 2; i * i < n; i++) {
if (primes[i]) {
for (int j = i * i; j < n; j += i) {
primes[j] = false;
}
}
}
return primes;
}
}