0

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

גלעד ברקן
  • 23,602
  • 3
  • 25
  • 61
roboto
  • 13
  • 2
  • 1
    Voted to close because the question lacks focus and detail. OP has not provided any of their own code aside from 3 short placeholder functions that do nothing. – Yogi Jun 12 '22 at 06:20

1 Answers1

2

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);
}
trincot
  • 317,000
  • 35
  • 244
  • 286
  • take into account [this example](https://pastebin.com/raw/J4K4fPsp), it returns in form of array, as SO has console.log limit. I have set the *max to 3*, the only problem is it returns some items,duplicated. – roboto Jun 13 '22 at 07:52
  • I solved it with `sl=Array.from([...new Set(sl)]);`(i put it before console.log),it filtered the duplicates, anyway thanks for your answer, *I never thought it would be that easy* – roboto Jun 13 '22 at 07:55
  • I think I need 15 rep. to vote, but thanks, I have marked this as answer, I will vote when i get that privilledge – roboto Jun 13 '22 at 08:13
  • Thank you for your feed-back! I updated the recursive function with an extra parameter, so it will not produce duplicates. – trincot Jun 13 '22 at 08:56