**The Challenge:**

1 2 3 4 5 |
Find the smallest common multiple of the provided parameters that can be evenly divided by both, as well as by all sequential numbers in the range between these parameters. The range will be an array of two numbers that will not necessarily be in numerical order. e.g. for 1 and 3 - find the smallest common multiple of both 1 and 3 that is evenly divisible by all numbers between 1 and 3. |

**The solution should return:**

1 2 3 4 5 6 7 8 9 10 11 |
smallestCommons([1, 5]) should return a number. smallestCommons([1, 5]) should return 60. smallestCommons([5, 1]) should return 60. smallestCommons([1, 13]) should return 360360. |

**Some helpful links:**

Least Common Multiple (LCM) Calculator

**Starter Code:**

1 2 3 4 5 |
function smallestCommons(arr) { return arr; } smallestCommons([1, 5]); |

This algorithm wasn’t too bad. I knew that involved the Euclidean Algorithm for the Greatest Common Divisor(aka Greatest Common Factor), the Euclidean Algorithm for the Least Common Multiple (which depends on the computation of the GCD), and that my solution would depend on those two formulas. I also knew that I was not just dealing with two array elements. These elements denoted the min and max of a range of elements. In this case, a range of numbers.

My solution had to to achieve the following:

- Find the least common multiple of a given array of 2 numbers and the range of numbers between them.
- The two numbers provided will not necessarily be in numerical order, so the solution will have to account for that.
- The arr containing the lcm of the range of numbers should not return in the form of an array, but as a number.

It was back to the provided arguments and expected outcomes drawing board to find common (or uncommon) pattern(s). I immediately noticed that all the arrays had ascending numbers except for one, which had descending numbers. I also saw that there were always only two numbers in each provided array.

The first thing to do however, was to start off the solution with the Euclid Algorithm for the Greatest Common Divisor followed by the Euclid Algorithm for the Least Common Multiple:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// Euclid Algorithm for the Greatest Common Divisor function gcd(a, b) { return !b ? a : gcd(b, a % b); } // Euclid Algorithm for the Least Common Multiple function lcm(a, b) { return a * (b / gcd(a, b)); } function smallestCommons(arr) { return arr; } smallestCommons([5, 1]); |

By itself, with help from function gcd(), function lcm() only takes care of finding the least common multiple of the two numbers in the array argument. I had to figure out a way to come up with the lcm of ALL the numbers within the range of arr = [a, b]. I wanted to find a way of mimicking the .reduce() method without actually using it to achieve this. In other words, I wanted to find a way of accumulating the lcm of all the numbers between arr[0] and arr[1] and “reducing” them to one lcm. With the .reduce() method, I usually used three parameters: the previousValue/initialValue returned in the last invocation of the callback, the currentValue or the current element being processed in the array, and then the array reduce is called upon. However, I wanted to use a for loop, because I had a set range of numbers in each array to iterate, and it was the simplest and most direct approach. I also had to set up two variables and their associated values equivalent to the previousValue and currentValue parameters of the .reduce() method. Lastly, if the order of the numbers in the array argument switched from ascending order to descending order, I had to make sure to reverse it back to ascending order. So this is what I came up with next:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Euclid Algorithm for the Greatest Common Divisor function gcd(a, b) { return !b ? a : gcd(b, a % b); } // Euclid Algorithm for the Least Common Multiple function lcm(a, b) { return a * (b / gcd(a, b)); } // LCM of all numbers in the range of arr = [a, b]; function smallestCommons(arr) { var i, result; // large to small - small to large if (arr[0] > arr[1]) { // only happens once. Means that the order of the arr reversed. arr.reverse(); } for (i = result = arr[0]; i <= arr[1]; i++) { // all numbers up to arr[1] are arr[0]. result = lcm(i, result); // lcm() makes arr int an integer because of the arithmetic operator. } return result; } |

This actually comprises the complete solution. Let’s break it down:

First we have the function for the greatest common divisor. The solution for that function is necessary in order to get the least common multiple for two numbers, which comes right after.

I had to declare two variables within the local scope of smallestCommons(), so I declare var i, result at the same time. i represents the counter in the for loop, and result represents the result parameter in the lcm(i, result) recursive function, using counter i and the instance of the result variable in the for loop. But then we need to calculate the lcm within the range of and including the two numbers in the array argument provided to us. 1 and 5, in the solution here. Since the order of the numbers of one of the array arguments is opposite from the rest, I have to account for that and before anything else. That’s because I want to make sure the order of the elements in the array are reversed before any looping takes place. Makes sense? If not, examine what is going on in the for loop for the answer. Since the reverse order only happens once, I can use an if statement. This is represented by if (arr[0] > arr[1]) { arr.reverse(); }. This means that if the first element/number in the array is larger than the second, the order should be reversed.

The next part is the tricky part. This is where calculation of the lcm for the range 1 – 5 takes place. In order to understand what is going on, we have to examine the role that the for loop plays here and how it works. First of all, the way I set up this for loop differs from your typical for loop. Typically, a for loop looks something like this:

1 |
for (var i = 0; i < num; i++) {} |

But I did:

1 |
for (i = result = arr[0]; i <= arr[1]; i++) {} |

For the first iteration of the loop, i = result which is = arr[0] which is equal to 1. i which is equal to 1 is <= arr[1], which is 5. and i++ means that after the iteration of the first loop, i will be incremented by 1 to equal 2. This will continue until i equals 5 and is then equal to arr[1], which is 5.

But that’s only the first part of the story. Following the for loop is the line result = lcm(i, result); This recursion of the lcm() function and its assignment to the result variable is what makes the magic happen.

- When i and result are first equal to 1 in the for loop, i as parameter of lcm() is equal to 1 and result as parameter of lcm() is also equal to 1. result = lcm(1,1). lcm(1,1) = 1. Therefore, result = 1.
- For the second iteration of the for loop, i = 2, and arr[0], therefore, is also = 2. the result variable to the left of the assignment operator = is equal to lcm(i, result). lcm(i, result) is lcm(2, 1) because the first result value from the first iteration of the for loop is carried into the lcm() function as a parameter for which the value is 1. Now result is = 2.
- For the the third iteration of the for loop, i = 3, and arr[0] is = 3. result, the parameter of lcm(i, result) is equal to 2. result = lcm(3,2). lcm(3,2) is equal to 6. That means that result = 6.
- For the fourth iteration of the for loop, i = 4, and arr[0] is = 4. result, the parameter of lcm(i, result) is equal to 6. result = lcm(4, 6). lcm(4, 6) is equal to 12. result is now = 12.
- For the 5th and final iteration of the for loop, i = 5 and arr[0] = 5. result, the parameter of lcm(i, result) is equal to 12. result = lcm(5, 12). lcm(5, 12) = 60. The for loop stops, and result is returned at the end of the smallestCommons() function right before the closing curly bracket.

You may wonder why I haven’t been explaining how result to the left of the assignment operator works in relation to the result parameter within lcm(i, result)? Yes, it can definitely be confusing. I kept that for last. The result in the for loop refers to the result parameter in the lcm() function. The result to the left of the assignment operator following the for loop represents a RE-ASSIGNMENT of the result variable. Each time the for loop goes through an iteration, this result is re-assigned a new value of lcm(i, result). This new value then becomes the value, or rather result argument passed to the lcm() function after the next iteration of the loop.

I almost forgot to mention one last little detail my solution had to (and did) achieve, and I’ll explain why it did.

You may be wondering why arr is not returned as an array, but as a number. That’s because the lcm function involves arithmetic, and the use of arithmetic operators on number elements in an array result in the return of numbers and not arrays of numbers.

**JSHint Metrics:**

1 2 3 4 |
There are 3 functions in this file. Function with the largest signature take 2 arguments, while the median is 2. Largest function has 6 statements in it, while the median is 1. The most complex function has a cyclomatic complexity value of 3 while the median is 2. |

**Solution:**

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// Euclid Algorithm for the Greatest Common Divisor function gcd(a, b) { "use strict"; return !b ? a : gcd(b, a % b); } // Euclid Algorithm for the Least Common Multiple function lcm(a, b) { "use strict"; return a * (b / gcd(a, b)); } // LCM of all numbers in the range of arr = [a, b]; function smallestCommons(arr) { "use strict"; var i, result; // large to small - small to large if (arr[0] > arr[1]) { // only happens once. Means that the order of the arr reversed. arr.reverse(); } for (i = result = arr[0]; i <= arr[1]; i++) { // all numbers up to arr[1] are arr[0]. result = lcm(i, result); // lcm() makes arr int an integer because of the arithmetic operator. } return result; } smallestCommons([5, 1]); |

**Solution in ES6:**

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Euclid Algorithm for the Greatest Common Divisor function gcd(a, b) { return !b ? a : gcd(b, a % b); } // Euclid Algorithm for the Least Common Multiple function lcm(a, b) { return a * (b / gcd(a, b)); } // LCM of all numbers in the range of arr = [a, b]; function smallestCommons(arr) { let i, result; // large to small - small to large if (arr[0] > arr[1]) { // only happens once. Means that the order of the arr reversed. arr.reverse(); } for (i = result = arr[0]; i <= arr[1]; i++) { // all numbers up to arr[1] are arr[0]. result = lcm(i, result); // lcm() makes arr int an integer because of the arithmetic operator. } return result; } smallestCommons([5, 1]); |

Comment Policy:Your words are your own, so be nice and helpful if you can. Please, only use your real name and limit the amount of links submitted in your comment. We accept clean XHTML in comments, but don't overdo it please. Comments are moderated, so spammy or malicious links will be removed.