Stack Overflow Asked by user13894959 on November 4, 2021
I tried my attempt at finding the smallest number that is divisible by numbers from 1 to n, and now I’m looking for advice on ways to further compact/make my solution more efficient. It would be pretty cool if there was an O(1) solution too.
def get_smallest_number(n):
"""
returns the smallest number that is divisible by numbers from 1 to n
"""
divisors = range(1, n+1)
check_divisible = lambda x: all([x % y == 0 for y in divisors])
i = 1
while True:
if check_divisible(i):
return i
i += 1
Another way to implement LCM
import time
from datetime import timedelta
start_time = time.monotonic()
def lcm(nums):
res = 1
for i in nums:
res = (res * i) // gcd(res, i)
return res
def gcd(a, b):
while b:
a, b = b, a%b
return a
print(lcm([8, 9, 10, 11, 12, 13, 14, 15]))
end_time = time.monotonic()
print(f'Duration: {timedelta(seconds=end_time - start_time)}')
Produces
360360
Duration: 0:00:00.000061
[Program finished]
Answered by Subham on November 4, 2021
Start by thinking about the factorial n!. This is obviously divisible by all numbers less then n, but is not the smallest such number. For example, you could divide n! by 6, and the smaller result would still be divisible by 2 and by 3, and hence still divisible by 6.
What numbers can we divide out? Composites, like 6, don't matter as long as all the required primes are present: 2 and 3 in that case. The primes give you the composites for free. So, concentrate on the primes.
Start with 2. Look at the powers of 2: 2, 4, 8, 16, ... Run through the powers of 2 until you find the highest power that is smaller than or equal to n. That is the only power of 2 you need, all the lower powers are unnecessary. You don't need to include 4 explicitly if n is 8 or higher because then you will have 8, 16 or whatever as a multiplier. Repeat for powers of 3: 3, 9, 27, 81, ... and so on through the primes up to sqrt(n). Beyond that point you only need the remaining primes less than n, since higher powers of those primes will exceed n.
Multiply the selected prime powers together to get the least n.
Use a Sieve of Eratosthenes to generate your initial list of primes up to n.
Answered by rossum on November 4, 2021
Mathematically, you are computing the least common multiple of 1, 2, ..., n
. lcm
is easily derived from gcd
, and lcm
is an associative operation. reduce
is useful for applying an associative operation to an interable. We can combine these ideas (as well as improvements due to Mark Dickinson and Eric Postpischil in the comments) to get a very fast solution:
from math import gcd
from functools import reduce
def lcm(a,b):
return a // gcd(a,b) * b
def get_smallest_number2(n):
return reduce(lcm,range(1 + n//2,n+1),1)
Some quick %timeit
results in IPython:
%timeit get_smallest_number2(15)
2.07 µs ± 26.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit get_smallest_number(15)
443 ms ± 5.75 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
For n = 15
it is thus over 200,000 times faster. Your function fails to produce any output long before n = 100
, but get_smallest_number2(100)
evaluates to 69720375229712477164533808935312303556800
almost instantly.
Answered by John Coleman on November 4, 2021
The idea is to add highest divider every iteration and check from high to low. Something like this:
n = int(input("n = "))
result = 0
while True:
result += n
for i in range(n, 1, -1):
if result % i != 0:
break
else:
break
print(result)
Answered by Olvin Roght on November 4, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP