As of python 3.9 you can compute the least common multiple directly:
from math import lcm
print(lcm(*range(1, 11)))
If that's "cheating", start with a loop like this:
from math import lcm
result = 1
for i in range (1, 11):
result = lcm(result, i)
Then replace lcm
with gcd
. The two-arg version of gcd
(greatest common divisor) has been around since python 3.5:
from math import gcd
result = 1
for i in range (1, 11):
result *= i // gcd(result, i)
Now gcd
is something that's relatively easy to implement using Euclid's algorithm. The idea is that if the GCD of two numbers x
and y
is g
, then x = a * g
and y = b * g
, with a
, b
relatively prime. If a
and b
weren't relatively prime, you could divide them by their common multiple and multiply g
by that amount. Let's say a >= b
. If x
is a multiple of y
, b
must be 1 (again, a
and b
are relatively prime) and therefore y = g
. Otherwise, c = a - b
must be relatively prime to both a
and b
(else they all have a common factor). We can therefore repeat the same reasoning for y
and z = x - y
until the two numbers become multiples of each other. The sequence must converge because the numbers decrease with every subtraction:
def gcd(x, y):
if x < y:
x, y = y, x
if x % y == 0:
return y
return gcd(x - y, y)
result = 1
for i in range (1, 11):
result *= i // gcd(result, i)
You can probably make this more efficient, but this should be sufficient to form an understanding of how to solve the problem.
A non-recursive GCD might be advisable in the general case, since python supports arbitrary sized integers. You could implemented it as
def gcd(x, y):
while True:
if x < y:
x, y = y, x
if x % y == 0:
return y
x -= y
Even if you're going to use brute force, I suggest that you do it with a little more intelligence. For example, you know that 10 < lcm <= 1 * 2 * ... * 9 * 10
you can therefore write your check like this:
numbers = range(1, 11)
product = 1
for i in numbers:
product *= i
for n in range(max(numbers) + 1, product + 1):
for i in numbers:
if n % i != 0:
break
else:
break
print(n)
The inner loop checks the current possibility against all the numbers
. If the loop terminates without breaking, n
is a multiple of all the numbers. This triggers the else
clause, which breaks out of the outer loop. The result is guaranteed to be correct because if nothing breaks the loop, n
will be the multiple of all the numbers.
In all the above cases, it's trivial to include the range [1, 20] in place of [1, 10].