
Project Euler 1: Multiples of 3 and 5

Peter Prevos |
842 words | 4 minutes
Share this content
This first Euler problem provides a gentle introduction to solving mathematical problems with code. This problem involves finding the sum of two related arithmetic sequences.
The natural numbers below 10 that are multiples of 3 or 5 results are 3, 5, 6 and 9. The sum of these numbers is $3+5+6+9=23$. Your assignment is to find the sum of all the multiples of 3 or 5 below 1000.
This problem is similar to one posed to a mathematics child prodigy that lived around the same time as Euler. When Carl Friedrich Gauss (1777–1855) was ten years old, his teacher gave his pupils a maths problem to ponder on. The teacher was perhaps seeking some quiet time for himself by giving the kids a hard problem. He asked them to sum all the numbers from 1 to 100, which surely would give him enough time to enjoy a cuppa.
Young Carl Gauss stood up after just a minute and confidently proudly raised his slate with 5050 written in large chalk letters to the teacher. All the other kids were still diligently adding numbers. How was Carl able to finish his task so quickly? The details and full truth of this story are lost in history. Perhaps Carl realised the solution while writing the series forwards and backwards:
$$1 + 2 + 3 + \ldots + 98 + 99 + 100$$
$$100 + 99 + 98 + \ldots + 3 + 2 + 1$$
Little Carl calculated the sum of some of the pairs and noticed a regularity:
$$1 + 100 = 2 + 99 = 3 + 98 = \ldots 100 + 1 = 99 + 2 = 98 + 3 = 101$$
Each of the pairs adds up to 101 and there are 50 pairs, therefore the sum of all numbers is half the sum of all pairs. Gauss was not the first to discover this method. Some thirteen hundred years earlier, Indian mathematician and astronomer Aryabhata had already discovered this method to sum a arithmetical sequence.
Proposed Solutions
This anecdote shows that there are two ways to solve this first problem. The smart method that Gauss used or the slow brute force method that his fellow pupils used. The brute force solution requires many steps to find the answer. The smart solution uses a one-step formula, such as the young Gauss and Aryabhata had figured out.
The most inefficient solution is to test whether all numbers between 1 and 999 are divisible by 3 or 5 and then add all these number. The R language provides several ways to step through a sequence of numbers.
The code below loops trough the numbers between 1 and 999.
# Project Euler 1: Multiples of 3 and 5
# Loop
answer <- 0
for (i in 1:999) {
if (i %% 3 == 0 | i %% 5 == 0) {
answer <- answer + i
print(i)
}
}
print(answer)
This first solution is elaborate. Using for-loops in R should always be a last resort in R coding because they are the slowest way to compute over a series of steps. The next two solutions solve this problem by using vector arithmetic. These methods are much faster because they run the loop directly in machine code instead of having to compile each step.
The solution for the first problem only requires one line of code when using vector arithmetic.
# Vector aritmetic
sum((1:999)[((1:999) %% 3 == 0) | ((1:999) %% 5 == 0)])
Analytical solution
Although the vector arithmetic is much faster than the for-loop, it is still not as fast as using the methods discovered by Aryabhata and Gauss. The two brute-force solutions are very fast because of the low number of steps to find a solution. An analytical solution reduces the processing time significantly, as it only requires one step.
The problem involves arithmetic progressions, which are sequences of numbers with a constant difference. The sequence 1, 4, 7, 10, 13, … is an arithmetic progression with a common difference of three.
We can generalise the method discovered by Gauss. The sum of an arithmetic progression ($S_n$), where $n$ is the number of elements and $a_1$ and $a_n$ are the lowest and highest value, is:
$$S_n= \frac{n(a_{1} + a_n)}{2}$$
The numbers divisible by $n=3$ can be expressed as:
$$\mathrm{sum}_3(999)=3+6+9+12+ \ldots + 999 = 3(1+2+3+4+ \ldots + 333)$$
We can now calculate the sum of all divisors by combining the above progression with the formula for arithmetic progressions as expressed in the above code, where $m$ is the divisor and $n$ the extent of the sequence. $p$ is the highest number less than $n$ divisible by $m$. In the case of 5, this number is 995.
$$p = n \lfloor (m/n) \rfloor$$
Substitution gives:
$$\mathrm{sum}_m(n) = p \frac{1+(p/m)}{2}$$
# Analytical solution
SumDivBy <- function(m, n) {
p <- floor(n / m) * m # Round to multiple of n
return (p * (1 + (p / m)) / 2)
}
SumDivBy(3, 999) + SumDivBy(5, 999) - SumDivBy(15, 999)
Share this content