javascriptfunctionloopsrecursioncombinations

Creating Internal Loops Dynamically


My code is working perfectly :

const i=['a','e','i','o','u'];
let q=[];

for(let t=0,l=i.length;t<l;++t)
{
    for(let e=t+1,l=i.length;e<l;++e)
    {
        for(let z=e+1,l=i.length;z<l;++z)
        {
            q.push([i[z],i[e],i[t]]);
        }
    }
}

console.table(q);

But my goal is to make the internal loops dynamically so I could modify the number on the internal loops (3 at that specific case).

For example if I would want to modify the internal loops to 4 I would need to rewrite the code as such:

const i=['a','e','i','o','u'];
let q=[];

for(let t=0,l=i.length;t<l;++t)
{
  for(let e=t+1,l=i.length;e<l;++e)
  {
    for(let z=e+1,l=i.length;z<l;++z)
    {
      for(let c=z+1,l=i.length;c<l;++c)
      {
        q.push([i[c],i[z],i[e],i[t]]);
      }
    }
  }
}

console.table(q);

Therefore, I want to be able to make the internal loops DYNAMICALLY with the same exact formula.


Solution

  • This is where you can use recursion. This means you have a function that takes care of creating subarrays of a given size, but relies on the following observation:

    If we can do the job for subarrays which are one item shorter than the given size, then we can do it also for the given size: we just execute the function to generate the arrays that are one item shorter, and then append to each the "current" element.

    Here is a recursive implementation that outputs the same table as your example:

    function getSubarrays(arr, depth, take=0) {
        if (depth <= 0) return [[]]; // One result: an empty subarray
        depth--;
        const subarrays = [];
        for (let i = take; i < arr.length - depth; i++) {
            for (const subarray of getSubarrays(arr, depth, i + 1)) {
                subarrays.push([...subarray, arr[i]]);
            }
        }
        return subarrays;
    }
    
    const arr = ['a','e','i','o','u'];
    const results = getSubarrays(arr, 3);
    // Output with console.log
    for (const row of results) console.log(...row);

    So the second argument given to getSubarrays is the number of nested loops you want to execute. This argument is decreased one step at a time in recursion.