MC From Scratch
MC From Scratch

Reputation: 475

Converting Sum of Primes Python Code to Java Code

basically I need help with translating the following code in Python to Java.

I tried to learn a bit of Python the past day so I can convert it, but there are things I don't understand. I tried to implement it in Java but still it does not work. Without seeing a 'correct' Java translation, I cannot see where my algorithm goes wrong, and where my conversion has a mistake. The code uses dynamic programming to evaluate the sum of all primes that are smaller than n. If I am not mistaken, the 'assert' is synonymous to java 'while' but.. not entirely sure. Especially I am uncertain about the 3 lines that come after it. The rest I think I can convert. So I would appreciate if anyone can help me with the conversion of this code to Java, because I just couldn't translate all of it, even though it's a rather short code. Thanks.

def SOP(n):
    r = int(n**0.5)
    assert r*r <= n and (r+1)**2 > n
    V = [n//i for i in range(1,r+1)]
    V += list(range(V[-1]-1,0,-1))
    S = {i:i*(i+1)//2-1 for i in V}
    for p in range(2,r+1):
        if S[p] > S[p-1]: 
            sp = S[p-1]
            p2 = p*p
            for v in V:
                if v < p2: break
                S[v] -= p*(S[v//p] - sp)
    return S[n]

My attempted Java code:

public static long sumOfAllPrimesBelowLimit (long n)
    {
        long r = (long) Math.sqrt(n);
        ArrayList <Long> S = new ArrayList<Long>();

        while (r*r<=n&&(r+1)*(r+1)>n)
        {
            ArrayList <Long> V = new ArrayList <Long> ();
            for (long i = 1;i<=r+1;i++)
                V.add(n/i);

            // V += list(range(V[-1]-1,0,-1)) - I don't know what this means at all

            for (long i:V)
                S.add(i*(i+1)/2-1);
            for (int p=2;p<=r+1;p++)
                if (S.get(p)>S.get(p-1))
                {
                    long sp=S.get(p-1);
                    long p2 = p*p;
                    for (long v:V)
                    {
                        if (v<p2)
                        {
                            break;
                        }
                        S.add((int) v, S.get((int) v)-p*(S.get((int) (v/p))-sp));
                    }
                }
        }
        return S.get((int) n);
    }

I know it's not 100% complete, because I couldn't translate all of it. I think it would be better to use HashMap but first I want to get the basics to run properly.

Upvotes: 0

Views: 85

Answers (1)

Green Cloak Guy
Green Cloak Guy

Reputation: 24691

assert is, if anything, synonymous to Java assert (in that it throws an error if not met). Python has a while loop that works the same way as Java's while loop.

That said, here's some Java. I have no way to test this in my current situation, and I haven't done Java for a while, but it should more-or-less work. You might need to make some casts between int and Integer (or replace everything with longs, idk), but your compiler/stacktrace should tell you where.

public int SOP(int n) {
    // r = int(n**0.5)
    int r = (int) Math.sqrt(n);                                 
    //  assert r*r <= n and (r+1)**2 > n
    if(!(r * r <= n && (r+1) * (r+1) > n))
        throw new IllegalArgumentException("Assertion error");
    // V = [n//i for i in range(1,r+1)]
    ArrayList<Integer> V = new ArrayList<Integer>();
    for(int i = 1; i < r+1; i++)
        V.add(n / i);
    //V += list(range(V[-1]-1,0,-1))
    for(int i = V[V.size()-1]; i > 0; i--)
        V.add(i);
    // S = {i:i*(i+1)//2-1 for i in V}
    HashMap<Integer, Integer> S = new HashMap<Integer, Integer>();
    for(int i : V)
         S.put(i, (i*(i+1)/2 - 1));
    // for p in range(2,r+1):
    for(int p = 2; p < r+1; p++ {
        // if S[p] > S[p-1]: 
        if S.get(p) > S.get(p-1) {
            // sp = S[p-1]
            int sp = S.get(p-1);
            // p2 = p*p
            int p2 = p * p;
            // for v in V:
            for(int v : V) {
                // if v < p2: break
                if(v < p2)
                    break;
                // S[v] -= p*(S[v//p] - sp)
                S.put(v, S.get(v) - p*(S.get(v/p)-sp));
            }
        }
    }
    // return S[n]
    return S.get(n);
}

That said, this algorithm is somewhat obtuse. If it were me, I'd just code an is_prime() function, and then count up from 0 to n and add the ones that were. The latter step of which could be done in a single line of python, and wouldn't take this many in Java.

Upvotes: 1

Related Questions