Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I speed up this program?

I am currently attempting to solve a ProjectEuler problem and I have got everything down, except the speed. I am almost certain the reason the program executes so slowly is due to the nested loops. I would love some advice on how to speed this up. I am a novice programmer, so I am not familiar with a lot of the more advanced methods/topics.

public class Problem12 {

    public static void main(String[] args) {
        int num;

        for (int i = 1; i < 15000; i++) {
            num = i * (i + 1) / 2;
            int counter = 0;

            for (int x = 1; x <= num; x++) {
                if (num % x == 0) {
                    counter++;
                }
            }
            System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers.");
        }
    }
}

EDIT : Below is the new code that is exponentially faster. Removed the constant line printing as well to speed it up even more.

public class Problem12 {

    public static void main(String[] args) {
        int num;

        outerloop:
        for (int i = 1; i < 25000; i++) {
            num = i * (i + 1) / 2;
            int counter = 0;

            double root = Math.sqrt(num);
            for (int x = 1; x < root; x++) {
                if (num % x == 0) {
                    counter += 2;
                    if (counter >= 500) {
                        System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers.");
                        break outerloop;
                    }
                }
            }
        }
    }
}
like image 800
jzbakos Avatar asked Oct 11 '16 20:10

jzbakos


1 Answers

For starters, when looking at divisors, you never need to go further than the root square of the number, because each divisor below the square root has an equivalent above.

n = a * b => a <= sqrt(n) or b <= sqrt(n)

Then you need to count the other side of the division:

double root = Math.sqrt(num);
for (int x = 1; x < root; x++) {
    if (num % x == 0) {
        counter += 2;
    }
}

The square root is special because it counts only once if it is integer:

if ((double) ((int) root) == root) {
    counter += 1;
}
like image 126
njzk2 Avatar answered Oct 24 '22 05:10

njzk2