Home > OS >  Find all possible function combinations
Find all possible function combinations

Time:06-14

I have 3, js functions:

function f1(a,b){
return 0;//returns something
}
function f2(a,b){
return 0;//returns something
}
function f3(a){/*note that this has only 1 input: a*/
return 0;//returns something
}

I need to find all possible combinations of these functions up to two functions in a string that is, it need to return the below strings, in form of array

"f1(f1($,$),$)"//used functions:2:- f1,f1
"f1($,f1($,$))"//used functions:2:- f1,f1
"f1(f2($,$),$)"//used functions:2:- f1,f2
"f1($,f2($,$))"//used functions:2:- f1,f2
"f1(f3($),$)"//used functions:2:- f1,f3
"f1($,f3($))"//used functions:2:- f1,f3
"f1($,$)"//used functions:1:- f1

"f2(f1($,$),$)"//used functions:2:- f2,f1
"f2($,f1($,$))"//used functions:2:- f2,f1
"f2(f2($,$),$)"//used functions:2:- f2,f2
"f2($,f2($,$))"//used functions:2:- f2,f2
"f2(f3($),$)"//used functions:2:- f2,f3
"f2($,f3($))"//used functions:2:- f2,f3
"f2($,$)"//used functions:1:- f2

"f3(f1($,$))"//used functions:2:- f3,f1
"f3(f2($,$))"//used functions:2:- f3,f2
"f3(f3($))"//used functions:2:- f3,f3
"f3($)"//used functions:1:- f3
Notes:
  • $ represents some value that need not be interfered in this Q.s, so let $ ,be $ for this Q.s
  • the three js functions may vary to any extent, in my case 7 js functions, with six of them having two inputs ,and one function with one input
  • up to two functions in a string may vary to any extent, like up to 5 functions...

I have learnt to generate possible combinations ,as shown below

/*
 * Generate all possible combinations from a list of characters for a given length
 */
function* charCombinations(chars, minLength, maxLength) {
  chars = typeof chars === 'string' ? chars : '';
  minLength = parseInt(minLength) || 0;
  maxLength = Math.max(parseInt(maxLength) || 0, minLength);

  //Generate for each word length
  for (i = minLength; i <= maxLength; i  ) {

    //Generate the first word for the combination length by the repetition of first character.
    word = (chars[0] || '').repeat(i);
    yield word;

    //Generate other possible combinations for the word
    //Total combinations will be chars.length raised to power of word.length
    //Make iteration for all possible combinations
    for (j = 1; j < Math.pow(chars.length, i); j  ) {

      //Make iteration for all indices of the word
      for (k = 0; k < i; k  ) {

        //check if the current index char need to be flipped to the next char.
        if (!(j % Math.pow(chars.length, k))) {

          // Flip the current index char to the next.
          let charIndex = chars.indexOf(word[k])   1;
          char = chars[charIndex < chars.length ? charIndex : 0];
          word = word.substr(0, k)   char   word.substr(k   char.length);
        }
      }

      //Re-oder not neccesary but it makes the words are yeilded alphabetically on ascending order.
      yield word.split('').reverse().join('');
    }
  }
}

let combinations = charCombinations('abc', 1, 3);
let combination = 0;
var carray = [];
while (typeof combination != "undefined") {
  combination = combinations.next().value
  carray.push(combination);
}
carray.pop();

console.log(carray);

Its is a modification to this blog,
But I don't know how to implement it with a string that is in a form of function with brackets,
I guess using xml will help as shown in here
I have practice of using xml for data and algorithm handling in js,
But still I don't know how to implement it.,Please help

CodePudding user response:

You can use a recursive generator that takes the following input:

  • An array of function-call strings with $ placeholders for arguments, so for example: ["f1($,$)", "f2($,$)", "f3($)"]. This means you can control how many arguments a function takes, and how many take just 1 (always 1 in your question), or 2, or even more.

  • A minimum number of function calls to generate per output (this seems to be always 1 in your question)

  • A maximum number of function calls to generate per output (like 7)

The algorithm passes the current string to the recursive call which can extend it further until the time comes to yield it. The idea is that every $ is found in the string and can be replaced with more nested function calls.

Snippet:

function* combinations(funcs, minCount, maxCount, result="$", start=0) {
    if (maxCount <= 0) return yield result;
    for (let f of funcs) {
        for (let i = result.indexOf("$", start); i >= 0; i = result.indexOf("$", i   1)) {
            yield* combinations(funcs, minCount - 1, maxCount - 1, result.slice(0, i)   f   result.slice(i   1), i);
        }
    }
    if (minCount <= 0) yield result;
}


// Example run
for (let s of combinations(["f1($,$)", "f2($,$)", "f3($)"], 1, 2)) {
    console.log(s);
}

In case your input is just the function objects (references), then you need some preprocessing so to get their names and the number of parameters they are defined with:

function describe(f) {
    return `${f.name}(${Array(f.length).fill("$").join(",")})`;
}

function* combinations(funcs, minCount, maxCount, result="$", start=0) {
    if (maxCount <= 0) return yield result;
    for (let f of funcs) {
        for (let i = result.indexOf("$", start); i >= 0; i = result.indexOf("$", i   1)) {
            yield* combinations(funcs, minCount - 1, maxCount - 1, result.slice(0, i)   f   result.slice(i   1), i);
        }
    }
    if (minCount <= 0) yield result;
}


// Example run
function f1(a,b){ return 0; }
function f2(a,b){ return 0; }
function f3(a){ return 0; }

for (let s of combinations([f1, f2, f3].map(describe), 1, 2)) {
    console.log(s);
}

  • Related