7
\$\begingroup\$

Given:

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.

Solution:

class Main {
  public static int sumMupltiple(int num, int limit) {
      int numOfMulitples = (limit - 1) / num;
      return num * (numOfMulitples * (numOfMulitples + 1) / 2);
  }

  public static void main(String[] args) {
    System.out.println(
        sumMupltiple(3, 1000) + sumMupltiple(5, 1000) - sumMupltiple(15, 1000));

  }
}

Is there a clearer approach for Java?

\$\endgroup\$
7
\$\begingroup\$

Meta comments

Is your intention to create a separate Java program for each of the hundreds of Project Euler problems? If you plan on completing more than a handful of them, I would recommend finding a way to consolidate your solutions to all problems into a single program. You will find a significant amount of overlap between certain questions, so being able to create "helper" routines will benefit you greatly. Consider adding in some testing, validation, and timing framework to make sure your results are correct and being solved within a reasonable amount of time (i.e., PE's suggested 1-minute duration).

Algorithmic Comments

As this is a code review, and not an algorithm review, and because I don't want to spoil yours or anyone else's Project Euler experience, I'll keep this brief. Your algorithm is good; you've already used the closed-form equation for these triangle numbers and done some math. You can actually take the math a step further, but then the programming is trivialized and entirely problem #1-specific.

Code Comments

Creating the general sumMultiple() routine is good, as it is general enough to probably prove useful later on.

I would highly recommend factoring this line into its own problem001() subroutine:

 sumMupltiple(3, 1000) + sumMupltiple(5, 1000) - sumMupltiple(15, 1000));

Then in your main() function, you need only do:

System.out.println(problem001());

And the self-documenting nature of that naming scheme makes it pretty clear that you are printing the result of problem 001. It might seem a little silly in this case, but not all problems will be one-liners, and consistency is probably better than brevity in this case.

If you do decide to take some of my "meta comments" advice later, it will be even easier to organize your program.

\$\endgroup\$
  • \$\begingroup\$ Cool, I will keep that in mind for the coming problems. I was actually using YAGNI approach. \$\endgroup\$ – CodeYogi Sep 15 '15 at 16:48
  • \$\begingroup\$ Also, I don't know the actual number but don't you think a single class can be too huge after solving 100 or more problems? \$\endgroup\$ – CodeYogi Sep 15 '15 at 16:49
  • \$\begingroup\$ In this case, YAGNI (you are gonna need it!) if you do more than a few problems. Don't take guidelines as law; develop and use your instincts. Pre-optimization isn't always wrong. I also have no compunctions against large (even very large!) classes/source files as long as they're still cohesive and easily maintained. At some point, you will probably start splitting groups of useful helper routines into their own libraries, however. And, if it gets difficult for you to actually edit the source file, look into editors with folding, or split into manageable chunks. \$\endgroup\$ – type_outcast Sep 15 '15 at 16:57
  • \$\begingroup\$ It's also worth mentioning that things like Project Euler are always going to lead to a few unusual coding practices that don't translate well to more common real-world projects. In real world projects, for example, it's not often that you'll find 500+ unique subroutines that all belong together. \$\endgroup\$ – type_outcast Sep 15 '15 at 16:59
5
\$\begingroup\$

Naming

I find it funny that you misspelled "multiple" in two different ways. Clearly you are carelessly using some code-completion feature in your text editor.

Main is a very generic name for your class. I suggest public class Euler1 or something like that.

\$\endgroup\$
-1
\$\begingroup\$

The given solution doesn't work for very large inputs like \$1<limit<10^9\$. Hence here is the solution using BigInteger.

import java.util.Scanner;
import java.math.BigInteger;

public class Solution {
    public static BigInteger sumMupltiple(int num, int limit) {
        BigInteger sum = BigInteger.ZERO;
        limit = limit - 1;
        BigInteger numMultiples = new BigInteger(""+limit).divide(new BigInteger(""+num));
        return sum.add(
            numMultiples.multiply(numMultiples.add(new BigInteger(""+1))).divide(new BigInteger(""+2)).
            multiply(new BigInteger(""+num)));
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int T = input.nextInt();
        for (int i = 0; i < T; i++) {
            int N = input.nextInt();
            System.out.println(
                sumMupltiple(3, N).
                add(sumMupltiple(5, N)).
                subtract(sumMupltiple(15, N)));   
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ What's the point of BigInteger.ZERO.add(…)? \$\endgroup\$ – 200_success Sep 24 '15 at 6:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.