Smallest Common Multiple Algorithm Challenge - TypeError

Smallest Common Multiple Algorithm Challenge - TypeError
0.0 0

#1

Hi guys,
I am doing the smallest common multiple - intermediate algo and trying my own implementation which gives me a TypeError for the function filArr(…).
Can someone probably have a look? I am really stuck and want to try the array.filter method.

I would be very grateful, thank you very much

////smallest common multiple

function smallestCommons(arr) {
arr.sort();
var rArr=[];
//Array of multiplies of the higher Array value
for (var i=1;i<20;i++){
rArr.push(arr[1]*i);
}

//function for filter, looks if multiplies of a numb(er) is in array
function filArr(numb){
for (var j=1;j<20;j++){
if(rArr.indexOf(j*numb)!==-1) return true;
}
return false;
}

//loop for all numbers in between original array numbers
var z = arr[1]-1;
while (z>0 && arr[0] !== z){
rArr.filter(filArr(z));
z–;
}

return rArr[0];
}


#2

It’s happening because of the line:

rArr.filter(filArr(z));

The Array.prototype.filter() takes a function as the first argument, a callback function. But your filArr() is returning a value of true to it, so the browser is sending you an error. Mine sends:

Uncaught TypeError: true is not a function
    at Array.filter (native)
    at smallestCommons (pen.js:42:10)
    at pen.js:51:clock1130:

#3

In addition the filArr(...) you passed to Array.prototype.filter() is illegal, and it should return some values if it passes the test.

You can explain what you’re trying to achieve with this implementation so we can help you better


#4

With an array of multiplies of the highest number I then need to see which of this numbers are also a multiple of the numbers in between the original array.
So like original array [3,5], then rArr would be 5,10,15,20,25,… and filArr(numb) should take the numbers 4 and 3 and check if multiplies of them match to rArr and only leave matching multiplies in rArr (filter for the matching ones).

Maybe I did get something wrong, that was just the solution I had in mind, and I never implemented a working filter-method so I don’t know how to do it here.
I thought the filter function keeps the current array value when the callback is true which isn’t the case I guess.

Do you have a advice here?

And really thanks for your replies


#5

Hi, I’m learning about the .filter() method too, and although I don’t have a solution, my understanding is this

  • rArr.filter will iterate over rArr 19 times in total (once for each element of rArr). and this “length” (19) is probably different to the “length” of all numbers in between the original array numbers e.g if arr = [5, 11], then this sequence is 7 long (inclusive). see? So, I’m thinking maybe filter won’t iterate the correct number of times here, and you may prefer a for loop which iterates 7 (or however long the sequence is) times.
    Maybe this helps :slight_smile:

Secondly, if you are interested in trying .reduce() with the Euclidean Algorithm, I’m using that method, and here’s my code. Unfortunately, my .reduce() is not working…lol. I need help too. p.s do you know how we publish properly formatted i.e. indented code here, in this discussion forum?

Summary
function smallestCommons(arr) {
  var seqArr = [];
  for (var i = arr[0]; i <= arr[1]; i++) {
    seqArr.push(i);
  }
  
  function LcmOf2Nums(a, b) {
    var arr = [[a,b]];
    var j = 0;
    while (arr[j][1] > 0) {
      arr[j].push(arr[j][0] % arr[j][1]);
      arr.push([arr[j][1], arr[j][0] % arr[j][1]]);
      j++;
    }
    arr.pop();
    var hcf = arr[arr.length-2][2];//arr[j-1][2]
    var lcm = a * b/hcf;
    return lcm;
  }
  
  //find the lcm of the first pair in seqArr, and then find the lcm of this lcm and the third element of the array...keep going until we reach the end of seqArr :)
  var lcmOfSeq = seqArr.reduce(function(accum, currVal) {
    console.log(accum, currVal);
    return LcmOf2Nums(accum, currVal);
  }); 
  //console.log(lcmOfSeq);
  return lcmOfSeq;
}

smallestCommons([5,11]);

#6

Oh, actually there was no problem with the .reduce() method in the above post. I adjusted the Euclidean Algorithm to not run when b is divisible by a, so now, this algorithm works :smiley: :smiley: :smiley:

function smallestCommons(arr) {
  arr.sort(function(a, b) {
    return a - b;
  });

  var seqArr = [];
  for (var i = arr[0]; i <= arr[1]; i++) {
    seqArr.push(i);
  }
  
  function LcmOf2Nums(a, b) {
    if (a % b !== 0) {
      var arr = [[a,b]];
      var j = 0;
      while (arr[j][1] > 0) {
        arr[j].push(arr[j][0] % arr[j][1]);
        arr.push([arr[j][1], arr[j][0] % arr[j][1]]);
        j++;
      }
      arr.pop();
      var hcf = arr[arr.length-2][2];//arr[j-1][2]
      return a * b/hcf; //i.e. the lcm when a=60 and b = 42
    } else {
      return a; //i.e. the LCM when a=60, and b=30
    }
  }
  
  //find the lcm of the first pair in seqArr, and then find the lcm of this lcm and the third element of the array...keep going until we reach the end of seqArr :)
  var lcmOfSeq = seqArr.reduce(function(accum, currVal) {
    return LcmOf2Nums(accum, currVal);
  }); 
  return lcmOfSeq;
}

smallestCommons([11,13]);

#7

hi from me again. Ok, last, final tip about .filter()
If you are interested in learning more about .filter() then the next algorithm ‘Finders Keepers’ is really, really good for practising the essence of the .filter() method.
In fact ‘Finders Keepers’ can be solved in 2 lines :slight_smile:

function findElement(arr, func) {
  var newArr = arr.filter(func);
  return newArr[0];
}

findElement([1, 2, 3, 4], function(num){ return num % 2 === 0; });

#8

@Caruso33, I kinda debugged your code for the filArr(...) it works now on the Array.prototype.filter() so you can continue from here. The filArr(...) should have a condition that passes or fail, you don’t need to tell it to return true or false, it does that by evaluation and the Array.prototype.filter() should return some values (a new array) which I pushed into a new array called someArr. Note that I removed the filArr(z) and used filArr instead in the Array.prototype.filter(), that’s because it created another empty function which doesn’t have any parameter and will not return any value thereby performing and illegal action on it, that’s the reason for the TypeError. You should read more on scopes. By doing so, am passing the function into the Array.prototype.filter() and not creating another. But then you should try the Euclidean algorithm with your implementation in case you don’t arrive at the answer. Here is the debugged code:

function smallestCommons(arr) {
arr.sort();
var rArr=[], someArr = [];
//Array of multiplies of the higher Array value
for (var i=1;i<20;i++){
  rArr.push(arr[1]*i);
}


//function for filter, looks if multiplies of a numb(er) is in array
function filArr(numb){
  for (var j=1;j<20;j++){
    return rArr.indexOf(j*numb)!==-1; 
  }
}

//loop for all numbers in between original array numbers
var z = arr[1]-1;
while (z>0 && arr[0] !== z){
 someArr.push(rArr.filter(filArr));
z--;
}

return someArr[0];
}

#9

@userGitHub34535 check this link Markdown quick reference on how to markdown to publish code because this forum editor uses markdown and so do other tech sites. I hope it helps.