0

Hello guys I am trying to create an LCM function that takes in two numbers. The findCommonMultiple() function in this piece of code basically returns an array for the prime factors for that number. What I'm trying to do in this function is to check if there are duplicates in both arrays and if there are any that number will be pushed inside a new array. After a number has been pushed the inner loop should break and continue to the next iteration. If both numbers are not equal to each other they both will be pushed. This also goes on even if one of the arrays goes over their index. After all the duplicate factors and unique ones have been pushed I will begin to multiply them and return the LCM of both numbers. I have yet to create a helper function for that but I need to fix this problem first.

  function leastCommonMultiple(num1, num2){
  var prime1 = findPrimeFactors(num1);
  var prime2 = findPrimeFactors(num2);
  var primes = []; 
  var lcm = 1;


  for(var i = 0; i < prime1.length; i++){
    var factor1 = prime1[i];
    for(var j = i; j < prime2.length; j++){
      var factor2 = prime2[j];
      if(factor1 === factor2){
        primes.push(factor1);
        break;
      } else if(factor1 === undefined && factor2 > 0){
        primes.push(factor2);
      } else if(factor2 === undefined && factor2 > 0){
        primes.push(factor1)
      } else {
        primes.push(factor1);
        primes.push(factor2);
        break;
      }
    }
  }
  return primes;
}

EDIT: So I'm adding a test case. So if I have values 26 and 24 passed I would get two arrays. One would be [2, 2, 2, 3] and the other would be [2, 13]. This function will take my duplicates in side the new array and add in all the others that aren't duplicates so: [2] is in first because both arrays have 2 and then [2, 2, 2, 3, 13] the rest of the numbers without duplicates gets added into the array.

3 Answers3

0

If all you need is unique items from both the arrays, I suggest doing it this way,

First concatenate the two arrays and store it in a new array, in this case,

var tempPrimes= prime1.concat(prime2);

Then just write a simple filter to filter out unique values,

var primes = tempPrimes.filter(function(item, pos){
  return tempPrimes.indexOf(item)== pos; 
});

If you also want to remove 0 values, then just modify it a bit,

var primes = tempPrimes.filter(function(item, pos){
  return tempPrimes.indexOf(item)== pos && tempPrimes[pos]!=0; 
});

Hope I helped :)

Edit (after further clarification of the question):

var tempPrimes= prime2.filter(function(item) {
  return prime1.indexOf(item) < 0;
});


var primes= prime1.concat(tempPrimes);
Elvis
  • 1,103
  • 8
  • 15
  • I need to also include duplicates. so if I have an one array that is: `[2,2,2,3]` and the other is `[2, 13]`. Then my new array should be `[2, 2, 2, 3, 13]`. –  Oct 16 '17 at 17:28
  • Hmmm, and what if it's [2,2,2,3] and the other is [2,2,13] ? you still want [2, 2, 2, 3, 13] ? – Elvis Oct 16 '17 at 17:45
  • Yes, [2, 2, 13] is 52 the lcm of 52 and 24 is still 312 so yes. –  Oct 16 '17 at 17:56
  • Edited the answer – Elvis Oct 16 '17 at 17:57
0

When your arrays of prime factors are sorted, which I think they are, you can just traverse them simultaneously. If one of the array heads is smaller than the other, advance that head and push it to the result array. If both array heads are equal, push the head value and advance both heads. That way, you don't have nested loops.

The following code does this and creates arrays or the least common multiple and the greatest common divisor at the same time:

var prime1 = findPrimeFactors(num1);
var prime2 = findPrimeFactors(num2);
var lcm = [];
var gcd = [];

let i = 0;
let j = 0;

while (i < prime1.length && j < prime2.length) {
    if (prime1[i] < prime2[j]) {
        lcm.push(prime1[i++]);
    } else if (prime1[i] > prime2[j]) {
        lcm.push(prime2[j++]);
    } else {
        gcd.push(prime1[i]);
        lcm.push(prime1[i]);
        i++;
        j++;
    }
}

while (i < prime1.length) lcm.push(prime1[i++]);
while (j < prime2.length) lcm.push(prime2[j++]);

Another way to solve this is to ceate a count dictionary for both numbers. Merge the two dicts by adding the maximum count for each key to the result dict. This method doesn't require sorted prime factor arrays:

var pmax = {};          // result count dict
var pmax2 = {};         // auiliary count dict of primes2

for (let i = 0; i < prime1.length; i++) {
    let p = prime1[i];

    pmax[p] = (pmax[p] || 0) + 1;
}

for (let i = 0; i < prime2.length; i++) {
    let p = prime2[i];

    pmax2[p] = (pmax2[p] || 0) + 1;
}

for (let k in pmax2) {
    pmax[k] = Math.max((pmax[k] || 0), pmax2[k]);
}

for (let k in pmax) {
    let n = pmax[k];

    while (n--) lcm.push(k);
}

Finally, the easiest way to calculate the least common multiple might be to calculate the greatest common divisor with Euclid's algorithm and to apply the relation

lcm(a, b) = a * b / gcd(a, b)

(But be careful, because that method might cause overflow for large numbers.)

M Oehm
  • 28,726
  • 3
  • 31
  • 42
0

There was a simpler way to get the lcm of two numbers. My solution was good but it needed more work.

   function lcm(num1, num2){
      for(var i = 1; i <= num1 * num2; i++){
        if(i % num1 === 0 && i % num2 === 0){
          return i;
        }
      }
    }