patternjavaModerate
Project Euler #1 efficiency
Viewed 0 times
projectefficiencyeuler
Problem
I've started solving Project Euler problems. Is the code completely optimized?
Question:
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 N.
My solution:
Question:
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 N.
My solution:
import java.util.LinkedList;
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int testCases = sc.nextInt();
for (int i = 0; i al = new LinkedList<>();
int sums = 0;
for (int i = 1; i < input; i++) {
if (isMulThree(i) || isMulFive(i)) {
al.add(i);
}
}
for (int count : al) {
sums = sums + count;
}
return sums;
}
}Solution
I had a general review primed up for this question, but other answers beat me to those more general aspects.
@TheKittyKat provided a good starting point on the most efficient means of calculating the sum of each sequence, and then subtracting the double-count
Now, the solution @TheKittyKat provides for each sequence, is, for example:
If we were to put this in a function:
So, having generalized that, we can do:
But, there's a trick, the function:
can be reduced to a single \$O(1)\$ operation using the math behind a Arithmetic Progression / sum-of-sequence
This boils down to the fact that the sum of a sequence:
$$
1k + 2k + ... + (n-1)k + nk = \tfrac{n(1k + nk)}{2}.
$$
The equation:
$$
\tfrac{n(1k + nk)}{2}
$$
can be rewritten as:
$$
\tfrac{kn(1 + n)}{2}
$$
Now, either \$n\$ or \$(1 + n)\$ is even, and any even number times any other even number, is even, so you can always safely halve it.
Thus, the function can be reduced to:
So, the end result, is:
@TheKittyKat provided a good starting point on the most efficient means of calculating the sum of each sequence, and then subtracting the double-count
Now, the solution @TheKittyKat provides for each sequence, is, for example:
for (int i = 5; i < n; i += 5) {
sum += i;
}If we were to put this in a function:
public static int sumOfSequence(int value, int limit) {
int sum = 0;
for (int i = value; value < limit; i += value) {
sum += i;
}
return sum;
}So, having generalized that, we can do:
int total = sumOfSequence(3, N) + sumOfSequence(5, N) - sumOfSequence(15, N);But, there's a trick, the function:
public static int sumOfSequence(int value, int limit) {
int sum = 0;
for (int i = value; value < limit; i += value) {
sum += i;
}
return sum;
}can be reduced to a single \$O(1)\$ operation using the math behind a Arithmetic Progression / sum-of-sequence
This boils down to the fact that the sum of a sequence:
$$
1k + 2k + ... + (n-1)k + nk = \tfrac{n(1k + nk)}{2}.
$$
The equation:
$$
\tfrac{n(1k + nk)}{2}
$$
can be rewritten as:
$$
\tfrac{kn(1 + n)}{2}
$$
Now, either \$n\$ or \$(1 + n)\$ is even, and any even number times any other even number, is even, so you can always safely halve it.
Thus, the function can be reduced to:
public static int sumOfSequence(int value, int limit) {
final int count = (limit - 1) / value;
return value * count * ( count + 1) / 2;
}So, the end result, is:
public static int sumOfSequence(int value, int limit) {
final int count = (limit - 1) / value;
return value * count * ( count + 1) / 2;
}
public static void main(String[] args) {
int limit = 1000;
int sum = -sumOfSequence(15, limit) + sumOfSequence(3, limit) + sumOfSequence(5, limit);
System.out.println(sum);
}Code Snippets
for (int i = 5; i < n; i += 5) {
sum += i;
}public static int sumOfSequence(int value, int limit) {
int sum = 0;
for (int i = value; value < limit; i += value) {
sum += i;
}
return sum;
}int total = sumOfSequence(3, N) + sumOfSequence(5, N) - sumOfSequence(15, N);public static int sumOfSequence(int value, int limit) {
int sum = 0;
for (int i = value; value < limit; i += value) {
sum += i;
}
return sum;
}public static int sumOfSequence(int value, int limit) {
final int count = (limit - 1) / value;
return value * count * ( count + 1) / 2;
}Context
StackExchange Code Review Q#67103, answer score: 13
Revisions (0)
No revisions yet.