1

Generate as many distinct primes P such that reverse (P) is also prime and is not equal to P.

Output: Print per line one integer( ≤ 10^15 ). Don't print more than 10^6 integers in all.

Scoring: Let N = correct outputs. M = incorrect outputs. Your score will be max(0,N-M).

Note: Only one of P and reverse(P) will be counted as correct. If both are in the file, one will be counted as incorrect.

Sample Output 107 13 31 17 2

Explanation

Score will be 1. Since 13,107,17 are correct. 31 is incorrect because 13 is already there. 2 is incorrect.

Here is the code I've written which is giving me output Out Of Memory error in Eclipse.

Since memory requirement is 256 MB, I set -Xmx256M, but since it's giving me an Out Of Memory error, I must have misunderstood the question or my code is buggy in terms of memory utilization. What am I doing wrong here? I'm getting the desired output for smaller lONGMAX like 10000 or 1000000.

public class ReversePrime {
    final static long lONGMAX=1000000000000000L;
    final static int MAXLISTSIZE=1000000;
    final static boolean[] isPrime=isPrime();
    public static void main(String...strings ){

        Set<Long> reversedCheckedPrime = new LinkedHashSet<Long>();
        int isPrimeLength=isPrime.length;
        for(int i = 0; i < isPrimeLength ; i++){
            if( isPrime[i]){
                long prime = 2 * i + 3;
                long revrse= reversePrime(prime);
                if ( (!(prime==revrse)) && (!reversedCheckedPrime.contains(revrse)) && 
                        (reversedCheckedPrime.size()<=MAXLISTSIZE)){
                    reversedCheckedPrime.add(prime);
                }
                if (reversedCheckedPrime.size()==MAXLISTSIZE){
                    break;
                }
            }
        }   

        for (Long prime : reversedCheckedPrime){
            System.out.println(prime);
        }

    }
    private static long reversePrime(long prime) {
        long result=0;
        long rem;
        while(prime!=0){
            rem = prime % 10;
            prime = prime / 10;
            result = result * 10 + rem ;
        }
        return result;
    }
    private static boolean[] isPrime() {
        int root=(int) Math.sqrt(lONGMAX)+1;
        root = root/2-1;
        int limit= (int) ((lONGMAX-1)/2);
        boolean[] isPrime=new boolean[limit];
        Arrays.fill(isPrime, true);
        for(int i = 0 ; i < root ; i++){
            if(isPrime[i]){
                for( int j = 2 * i * (i + 3 ) + 3, p = 2 * i + 3; j < limit ; j = j + p){
                    isPrime[j] = false;
                }
            }

        }
        return isPrime;
    }
}

Hackerearth Link

Cœur
  • 37,241
  • 25
  • 195
  • 267
Ankur Anand
  • 3,873
  • 2
  • 23
  • 44
  • Have you try to go to the debug mode ? – Gary SEBASTIANI Jun 01 '15 at 12:27
  • @GarySEBASTIANI Now i got one thing `boolean[] isPrime=new boolean[limit];` is taking this much memory 1382236159byte that means it's around `1382.236159MB ` if i'm not wrong should i use `Bitset` but then dividing by `8` won't make any difference in term of memory ? – Ankur Anand Jun 01 '15 at 12:43
  • Yes, look at my comment below. And you can have a look to http://stackoverflow.com/questions/1907318/java-boolean-primitive-type-size – Gary SEBASTIANI Jun 01 '15 at 12:44
  • 1
    @AnkurAnand You just don't need that many. For 1M results, 100M numbers should suffice (s. my answer). +++ The `BitSet` would help by factor 8, but I don't think you need it. – maaartinus Jun 01 '15 at 12:58
  • 1
    @SébastienLeCallonnec Title hacked – Cœur Sep 23 '17 at 04:44

3 Answers3

2

There are two possibilities:

  • You use -Xmx256M which means a 256 MB heap. But there's more than just the heap and your VM may get killed when it tries to get more.

  • You give 256 MB to your VM but your program needs more and gets killed. <---- As RealSkeptic says, this is the case.

In order to get 1M primes, you need to investigate some <100M numbers(*). So with a prime sieve working below 100_000_000, it should work. This way the sieve works for the reversed number as well. By skipping the evens, you need only 50 MB, so you can set the limit to maybe 100M.

You could reduce the memory used by a factor 8 by using bits instead of bytes. You could reduce it by a factor of 2 by ignoring numbers starting with an even digit, but this gets complicated.


(*) This is something you can easily try out before submitting.

maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • Thank you so much .. i understood that now since i needed only upto this number of primes 10^6.. If Possible for you can you suggest me way to reduce a hell lot of running time like you have always did in past.. or should i post separate question on codereview ? – Ankur Anand Jun 01 '15 at 13:43
  • @AnkurAnand Yes, post to CR, but first please first do some improvements yourself (at least let your IDE format it and improve naming a bit). Also measure and post the time the three parts take (`toPrime`, filling the set, and the output). Is it really too slow? – maaartinus Jun 01 '15 at 14:35
  • it's taking around 9 sec with some improvisation .. yeah will work around everything then only will post ! with all details that i get – Ankur Anand Jun 01 '15 at 14:57
  • 1
    @AnkurAnand Fine! I've optimized a lot and it took a while, but I'm proud of [my results](https://microbenchmarks.appspot.com/runs/43eadd8c-6d6c-4748-af60-6cc1aeef9466). It shows the timing for sieving up to 1e6 / 1e9 and nextPrime iterating all primes between 2 and 1e6 / 1e9. – maaartinus Jun 01 '15 at 15:35
2

You declare this:

final static long lONGMAX=1000000000000000L;

And then when you allocate your boolean array, you calculate this:

int limit= (int) ((lONGMAX-1)/2);

Based on that definition, limit will be 1,382,236,159. That's 1.3Gb, assuming a boolean takes one byte. You might be thinking that the VM only allocates one bit per boolean, but that's not how it works.

Consider using a java.util.BitSet instead.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
0

You actually should replace your boolean[] with a List as the out of memory probably is coming from this table. You're not using the best strategy, as you're stacking all of the value for every long existing. You better should only keep in memory the prime numbers, try to rethink the definition of a prime number, and go on an iterative deduction.

Gary SEBASTIANI
  • 302
  • 1
  • 15
  • No, he's doing sieving and with 1 byte per 2 numbers it's about as dense as your `List` and *it's much faster*. He's just needlessly allocating too much. – maaartinus Jun 01 '15 at 12:55
  • Yes, that is what I tried to explain, when I said that stacking all the number is probably not a good solution. I advised the List because with it, he could obtain the same result keeping only the prime values – Gary SEBASTIANI Jun 01 '15 at 13:12
  • 1
    Yes, but each value in the list takes at least 8 bytes for the object and 4 bytes for the reference. So it's 12 bytes per prime vs. 0.5 byte per number and that's equal in a range where on average every 24th number is a prime. +++ What's worse: You can do no efficient sieving with the list. – maaartinus Jun 01 '15 at 13:15