Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interesting Program behaviour for Project Euler p21

I have got a solution for problem 21 in python and it gives the right answer. I tried out someone else's java code and I get the same answer for a value of 10000 and 100000 but when 1000000 is tried, the solution returned by my code differs from two other solutions returned by java code even though all three solutions returned are same for tested values of 10000 and 1000000 and 50000. Anyone got any ideas?

My Python code

def amicable_pairs(n):
    """returns sum of all amicable pairs under n. See project euler for 
    definition of an amicable pair"""
    div_sum = [0]*n
    amicable_pairs_set = [0]*n
    for i in range(1, n):
        for j in range(i*2, n, i):
            div_sum[j] += i
    #for i in range(1, n):
     #   div_sum[i] = sum([j + i/j for j in range(2, int(math.sqrt(i)) + 1) if i % j == 0 and i != i/j])
      #  div_sum[i] = div_sum[i] + 1

    #print div_sum
    for j in range(n):
        if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:
            amicable_pairs_set[j] = j
            amicable_pairs_set[div_sum[j]] = div_sum[j]
    return sum(amicable_pairs_set)

Java code 1:

public class AmicableNumbers {

    public static void main(String[] args) {
        long strTime = System.currentTimeMillis();
        int sum_ami = 0;
        for (int j = 1; j < 1000000; j++) {
            int ad = sum_devisors(j);
            if (((sum_devisors(ad)) == j) && (j != ad)) {
                sum_ami += j;
            }
        }
        System.out.println(sum_ami);
        long endTime = System.currentTimeMillis();
        System.out.println("time is " + (endTime - strTime) + " ms");
    }

    public static int sum_devisors(int number) {
        if ((number == 1) || (number == 2)) {
            return 1;
        }
        int sum = 0;
        int k = (int) Math.sqrt(number);
        for (int i = 2; i < k; i++) {
            if (number % i == 0) {
                sum += i;
                sum += (number / i);
            }
        }
        if (k * k == number) {
            sum += k;
        }
        return (sum + 1);// every number divided by 1
    }
}

Java code 2:

import java.util.Scanner;

public class AmicableNumbers {

    /**
     * @author Pavan Koppolu
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //scan the input
        System.out.println("Enter a number, to find out sum of amicable numbers: ");
        Scanner scan=new Scanner(System.in);
        int input=scan.nextInt();
        long before=System.currentTimeMillis();
        // getting the result
        long result=sumOfAllAmicableNumbersUptoGivenNumber(input);
        long after=System.currentTimeMillis();
        // prints the result on the console
        System.out.println("Sum of all amicable numbers below "+input+" : "+result+" Elasped Time : "+(after-before)+" ms");
    }
    /*
     * calculate the sum of the amicable numbers upto the given number
     */
    private static long sumOfAllAmicableNumbersUptoGivenNumber(int input)
    {
        long sum=0,factorsSum=0,sumOfFactors=0; 
        for(long j=2;j<input;j++)
        {
            factorsSum=getFactorsSum(j);
            if(j!=factorsSum)
            {
                sumOfFactors=getFactorsSum(factorsSum);
                if(j==sumOfFactors)
                    sum+=j;
            }   
            else
                continue;
        }       
        return sum;
    }
    /*
     * find out the sum of the factors
     */
    private static long getFactorsSum(long j)
    {
        long sum=1;
        for(int k=2;k<=Math.sqrt(j);k++)
        {
            if(j%k==0)
                sum+=k+j/k;
        }
        return sum;
    }
}

In fact the solutions returned by all three above differ from each other for an input of 1000000

like image 280
cobie Avatar asked Sep 13 '26 05:09

cobie


1 Answers

The point is that there are amicable pairs where one partner is less than 1 million and the other is larger than 1 million, namely

(947835,1125765), (998104,1043096)

The Python code doesn't count them,

for j in range(n):
    if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:

but the Java code counts the smaller members of these pairs. That explains the output of the second Java code, since

25275024 + 947835 + 998104 == 27220963

The output of the first Java code is smaller because it omits the amicable pair

(356408, 399592)

The reason is that

356408 = 596*598

but in the code there is

int k = (int) Math.sqrt(number);
for (int i = 2; i < k; i++) {

thus the divisor sum is miscalculated for all numbers divisible by floor(sqrt(n)) that are not squares (Note that the second Java code miscalculates the divisor sum for all squares).

like image 56
Daniel Fischer Avatar answered Sep 14 '26 17:09

Daniel Fischer