javascriptarraysobjectecmascript-6array-algorithms

Matrix array algorithm logic in JavaScript


I am trying to solve this algorithm in JavaScript. How can I write a solution considering time complexity, considering the maximum key value is 3?

input1 = [{0: "small"},{0: "large"}]
output1 = [ 'small.', 'large.']
-----------------------------------------
input2 = [ {0: "small"},{0: "large"}, {1: "red"} ]
output2 = ['small.red', 'large.red']
-----------------------------------------
input3 = [{0: "small"},{0: "large"}, {1: "red"}, {2:"cake"} ]
output3 = ['small.red.cake', 'large.red.cake'}
-----------------------------------------
input4 = [{0: "small"},{0: "large"}, {1: "red"}, {1: "orange"}, {2: "cake"} ]
output4 = ['small.red.cake', 'large.red.cake', 'small.orange.cake', 'large.orange.cake'}
------------------------------------------
input5 = [ {0: "small"},{0: "large"}, {1: "red"},{1: "orange"},{1: "blue"},{2: "cake"},{2: "ice"}]
output5 = ['small.red.cake', 'large.red.cake', 'small.orange.cake', 'large.orange.cake', 'small.blue.cake', 'large.blue.cake', 'small.red.ice', 'large.red.ice', 'small.orange.ice', 'large.orange.ice', 'small.blue.ice', 'large.blue.ice']
] //12 combinations

My attempt: I purposely checking the index in if condition. and it is working as expected. I'm looking for the best solution.

const input5 = [ {0: "small"},{0: "large"}, {1: "red"},{1: "orange"},{1: "blue"},{2: "cake"},{2: "ice"}]

 let array1 = [];
let array2 = [];
let array3 = [];
input5.forEach(val => {
  if(val[0]) {
    array1.push(val[0]);
  }
  if(val[1]) {
    array2.push(val[1]);
  }
  if(val[2]) {
    array3.push(val[2]);
  }
});
const finalArray = [];
array1.forEach(val1 => {
  if(array2.length > 0) {
     array2.forEach(val2 => {
       if(array3.length > 0) {
         array3.forEach(val3 => {
           const finalVal = `${val1}.${val2}.${val3}`;
           finalArray.push(finalVal);
         })
       }else {
         const finalVal = `${val1}.${val2}`;
         finalArray.push(finalVal);
       }
     })
  }else {
    const finalVal = `${val1}.`;
    finalArray.push(finalVal);
  }
})
console.log(finalArray);

Solution

  • This approach works, but whether it fits your time complexity requirements, I can't tell:

    const inputs = [
        [{ 0: "small" }, { 0: "large" }],
        [{ 0: "small" }, { 0: "large" }, { 1: "red" }],
        [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 2: "cake" }],
        [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 1: "orange" }, { 2: "cake" }],
        [{ 0: "small" }, { 0: "large" }, { 1: "red" }, { 1: "orange" }, { 1: "blue" }, { 2: "cake" }, { 2: "ice" }],
    ];
    
    function permutate(results, todo) {
        // If we have no layers left to go through, return the results
        if (!todo.length) return results;
        // Get first element of todo and store the rest for later
        const [layer, ...rest] = todo;
        // Flatmap that for example with:
        //   results = ['a', 'b']
        //   layer = [1, 2, 3]
        //  maps the results into:
        //    [ ['a.1', 'a.2', 'a.3'], ['b.1', 'b.2', 'b.3'] ]
        //  which will then be flattened together.
        results = results.flatMap(result => {
            return layer.map(value => `${result}.${value}`);
        });
        // After that, we permutate the rest of the layers
        return permutate(results, rest);
    }
    
    function getCombinations(input) {
        console.log('getCombinations for:', input);
        // Split per layer
        const layers = [];
        for (const obj of input) {
            for (const level in obj) {
                let layer = layers[level];
                if (!layer) layer = layers[level] = [];
                layer.push(obj[level]);
            }
        }
        // Now we have e.g. [ ['small', 'large'], ['red', 'orange'], ['cake', 'ice'] ]
        console.log('layers:', layers);
        // We immediately pass layer 0 as an array of results
        // then for every other layer, we build upon the (previous) results
        return permutate(layers[0], layers.slice(1));
    }
    
    for (const input of inputs) {
        console.log('========');
        const combs = getCombinations(input);
        console.log('combinations:', combs);
    }

    If your input was in a better format, that would be more performant and easier to code.