1

I am writting a function that finds the smallest common multiple between a given range of numbers. That is, a function that returns a number that all numbers present in a given range of numbers can divide through without a remainder.

I have been able to come up with a code that works but contains a while loop, however, when I increase the range of the numbers passed, my while loop breaks and returns "potential infinite loop"

QUESTION I wish to Write a function that finds the smallest common multiple of a range of numbers, given two parameters, were the smaller number is the lower range and the higher number is the upper range of the numbers.

Eg. when given ([1,3]), answer should be 6 Reason: ([1,3]) augments passed into the function, simply gives a range of [1,2,3] and the smallest common multiple of 1, 2, and 3 is 6. This means 6 is the smallest number that both 1,2 and 3 will divide and have no remainder.

Below is the code I came up with in JavaScript

const sum = (x,y) => x+y //
const myRangeArr = [ ]


function smallestCommonMultiple(arr) {
    
    let sortedArr = arr.concat([]).sort((a,b)=> a-b) //should incase the numbers do not  follow numeric asending order
  
for (let i = sortedArr[0] ; i<= sortedArr[1]; i++){
  myRangeArr.push(i)
} // this generates the full range of numbers

let smallestMultiple = myRangeArr[myRangeArr.length -1]


const result = () =>  myRangeArr.map( eachNum => smallestMultiple % eachNum).reduce(sum,0)
// when each number in myRangeArr is mapped and it returns their modulus, then I call the reduce function on it to sum all the modulus, if that number is a multiple of all the range of numbers, that means my answer will be zero (0)


while ( result() !== 0){
    smallestMultiple+= sortedArr[1] //since sortedArr[1] is the highest number in myRangeArr. Therefore let smllestMultiple keep increasing by the higest range number till the result() eventuall becomes equals to zero (0)
}

  return smallestMultiple;
}

console.log(smallestCommonMultiple([1,3])); // this works and outputs 6
console.log(smallestCommonMultiple([5,1])); // this works and outputs 60
console.log(smallestCommonMultiple([2,1])); // this fails and outputs 60...Answer should be 2
console.log(smallestCommonMultiple([23,18])); // this fails and outputs "Potential infinite loop detected on line 21"... answer should be 6056820

type here

CODE WITHOUT COMMENTS...


const sum = (x,y) => x+y
const myRangeArr = [ ]

function smallestCommonMultiple(arr) {
    let sortedArr = arr.concat([]).sort((a,b)=> a-b) 
  
    for (let i = sortedArr[0] ; i<= sortedArr[1]; i++){ myRangeArr.push(i) } 

    let smallestMultiple = myRangeArr[myRangeArr.length -1]

const result = () =>  myRangeArr.map( eachNum => smallestMultiple % eachNum).reduce(sum,0)

       while ( result() !== 0){ smallestMultiple += sortedArr[1]}

      return smallestMultiple;
}


console.log(smallestCommonMultiple([1,3])); // pass
console.log(smallestCommonMultiple([5,1])); // pass
console.log(smallestCommonMultiple([2,1])); // fail
console.log(smallestCommonMultiple([23,18])); // fail

Please, is there another better way I could resolve this problem, or is there something I am not considering (sure I know there must be) so I can escape these instances of failure?

Thanks!

I came up with a solution with help from this community.

function findSmallestCommonMultipleOfRangeOfNumbers(arr) {
let sortedArr = arr.concat([]).sort((a,b)=> a-b)
let min = sortedArr[0]
let max = sortedArr[1]
function range(min, max) {
const myRangeArr = [];
for (let i = min; i <= max; i++) {
myRangeArr.push(i);
}
return myRangeArr;
}

function gcd(a, b) {
return !b ? a : gcd(b, a % b);
}

function lcm(a, b) {
return (a * b) / gcd(a, b); 
}

let smallestCommonMultiple = min;
range(min, max).forEach(function(n) {
smallestCommonMultiple = lcm(smallestCommonMultiple, n);
});

return smallestCommonMultiple;
}

console.log(findSmallestCommonMultipleOfRangeOfNumbers([23,18]));

Ziglewis
  • 13
  • 6
  • Good thing is you don't have to invent an algorithm for LMC. Your algorithm is indeed not correct and very inefficient. See link at the top, Wikipedia and many other resources when your search the internet. – trincot Mar 16 '23 at 15:57
  • Thank you for taking the time to point this out. I do appreciate it. – Ziglewis Mar 16 '23 at 16:12

1 Answers1

0

The LCM of two numbers is their product divided by their greatest common divisor (GCD). The LCM of multiple numbers can be computed by a reduction operation, getting the LCM of the previous LCM and the next number in the array.

The GCD can be computed efficiently with the Euclidean Algorithm.

const gcd = (a, b) => b ? gcd(b, a % b) : a;
function lcm(a) {
  const l = Math.min(a[0], a[1]), r = Math.max(a[0], a[1]);
  return [...Array(r-l+1)].map((_,i)=>i+l).reduce((a, b) => a / gcd(a, b) * b, 1);
}
console.log(lcm([1,3]));
console.log(lcm([23,18]));
Unmitigated
  • 76,500
  • 11
  • 62
  • 80