YulePale
YulePale

Reputation: 7726

Recursive forEach() in javascript

I have a bunch of arrays of numbers for example:

let a = [1,2,3];
let b = [4,5,7];
let c = [11,13,17]

I want to create a function that tells me what combination(s) of numbers in the arrays multiplied by numbers in a different array result to a certain number. Below is the code I have so far:

// to get which combination of numbers result to 165
a.forEach(x=>{
    b.forEach(y=>{
        c.forEach(z=>{
        if(x*y*z==165){
            console.log(x,y,z)
        }
        })
    })
})

I want to create a function that can be fed an arrays of arrays of numbers such as: [[1,2],[2,5,],[7,11],[13,17]] and give back the combination(s) of numbers that, when multiplied, can result to a certain number.

Upvotes: 0

Views: 1696

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50807

This expresses the same algorithm from Nick's answer, but written in a very different style:

const findDivisors = (t, [ns, ...nss]) =>
  nss .length == 0
    ? ns .filter (n => n == t) .map (n => [n])
    : ns .flatMap (n => t % n == 0 ? findDivisors (t / n, nss) .map (ns => [n, ...ns]) : [])

const ns = [
  [1, 2, 3, 5, 6, 9],
  [2, 3, 4, 8, 12],
  [3, 5, 9, 12, 16, 18]
]

console .log (findDivisors (100, ns))
console .log (findDivisors (144, ns))
console .log (findDivisors (240, ns))
.as-console-wrapper {max-height: 100% !important; top: 0}

I prefer to work with expressions rather than statements. But as far as I see, it offers no advantages or disadvantages over Nick's answer except for questions of style.

It might be better to handle the empty array possibility too, which might look like:

const findDivisors = (t, [ns, ...nss]) =>
  ns == undefined
    ? []
  : nss .length == 0
    ? ns .filter (n => n == t) .map (n => [n])
    : ns .flatMap (n => t % n == 0 ? findDivisors (t / n, nss) .map (ns => [n, ...ns]) : [])

Upvotes: 1

Nick
Nick

Reputation: 147206

Here's a recursive function that takes an input number and array of arrays of numbers. It processes through the first array of numbers, finding any that are potential divisors, and if it does, recursively calling itself with the divided input and the balance of the array to see if there are any divisors from that pair of values. If so, they are appended to the current divisor to produce the result:

const findDivisors = (num, arrs) => {
  let result = [];
  if (arrs.length == 1) {
    return arrs[0].filter(n => n == num);
  }
  arrs[0].forEach(n => {
    if (num % n === 0) {
      findDivisors(num / n, arrs.slice(1)).forEach(r => result.push([n].concat(r)));
    }
  });
  return result;
}

let a = [1, 2, 3];
let b = [4, 5, 7];
let c = [11, 13, 17];
console.log(findDivisors(165, [a, b, c]));
console.log(findDivisors(136, [a, b, c]));

Upvotes: 2

Related Questions