I read an interesting DailyWTF post today, "Out of All The Possible Answers..." and it interested me enough to dig up the original forum post where it was submitted. This got me thinking how I would solve this interesting problem - the original question is posed on Project Euler as:
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest number that is evenly divisible by all of the numbers from 1 to 20?
To reform this as a programming question, how would you create a function that can find the Least Common Multiple for an arbitrary list of numbers?
I'm incredibly bad with pure math, despite my interest in programming, but I was able to solve this after a little Googling and some experimenting. I'm curious what other approaches SO users might take. If you're so inclined, post some code below, hopefully along with an explanation. Note that while I'm sure libraries exist to compute the GCD and LCM in various languages, I'm more interested in something that displays the logic more directly than calling a library function :-)
I'm most familiar with Python, C, C++, and Perl, but any language you prefer is welcome. Bonus points for explaining the logic for other mathematically-challenged folks out there like myself.
EDIT: After submitting I did find this similar question Least common multiple for 3 or more numbers but it was answered with the same basic code I already figured out and there's no real explanation, so I felt this was different enough to leave open.
An algorithm in Haskell. This is the language I think in nowadays for algorithmic thinking. This might seem strange, complicated, and uninviting -- welcome to Haskell!
The answer does not require any fancy footwork at all in terms of factoring or prime powers, and most certainly does not require the Sieve of Eratosthenes.
Instead, you should calculate the LCM of a single pair by computing the GCD using Euclid's algorithm (which does NOT require factorization, and in fact is significantly faster):
then you can find the total LCM my reducing the array using the above lcm() function:
In Haskell:
Which you can pass a list eg:
In expanding on @Alexander's comment, I'd point out that if you can factor the numbers to their primes, remove duplicates, then multiply-out, you'll have your answer.
For example, 1-5 have the prime factors of 2,3,2,2,5. Remove the duplicated '2' from the factor list of the '4', and you have 2,2,3,5. Multiplying those together yields 60, which is your answer.
The Wolfram link provided in the previous comment, http://mathworld.wolfram.com/LeastCommonMultiple.html goes into a much more formal approach, but the short version is above.
Cheers.
Here's my Python stab at it:
Step one gets the prime factors of a number. Step two builds a hash table of the maximum number of times each factor was seen, then multiplies them all together.
There's a fast solution to this, so long as the range is 1 to N.
The key observation is that if
n
(< N) has prime factorizationp_1^a_1 * p_2^a_2 * ... p_k * a_k
, then it will contribute exactly the same factors to the LCM asp_1^a_1
andp_2^a_2
, ...p_k^a_k
. And each of these powers is also in the 1 to N range. Thus we only need to consider the highest pure prime powers less than N.For example for 20 we have
Multiplying all these prime powers together we get the required result of
So in pseudo code:
Now you can tweak the inner loop to work slightly differently to get more speed, and you can precalculate the
primes_less_than(N)
function.EDIT:
Due to a recent upvote I decideded to revisit this, to see how the speed comparison with the other listed algorithms went.
Timing for range 1-160 with 10k iterations, against Joe Beibers and Mark Ransoms methods are as follows:
Joes : 1.85s Marks : 3.26s Mine : 0.33s
Here's a log-log graph with the results up to 300.
Code for my test can be found here: