Anhonime
Anhonime

Reputation: 55

"too much recursion" variations with repetitions

I'm trying to make a function that lists all the possible variations with repetitions. The one I made returns "too much recursion".

function variants(amount, chars, junk){
    var junkarray = junk.split(",");
    var newjunk;
    if(junkarray[junkarray.length-1]==amount){
        newjunk = ",";
    }
    if(junk.length==Math.pow(chars.length, amount)){
        console.log(junk);
        return;
    }else{
        for(var i = 0; i < chars.length; i++){
            variants(amount, chars, junk+newjunk+chars[i]);
        }
    }
}
variants(3, ["1", "2"],"");

Upvotes: 0

Views: 144

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50787

Although the answer from Ingo Bürk does explain something about why you hit the infinite recursion, it's solving a slightly different problem. Here is one solution that seems to work (Fiddle):

var variants = function(amount, chars, soFar) {
    soFar = soFar || [""];
    if (amount === 0) {return soFar;}
    var partials = soFar.map(function(partial) {
        return chars.map(function(char) {
            return partial.concat(char);
        });
    }).reduce(function(a, b) {return a.concat(b);}, []);
    return variants(amount - 1, chars, partials);
};

var v = variants(3, ["1", "2"]);
//=> ["111", "112", "121", "122", "211", "212", "221", "222"] 

Note that this will also run into recursion problems with data that is too big, but you should be fine for reasonably small sets of data.

Update

Possibly a bit cleaner would not be to announce the third parameter, which should only be used internally for the recursive call, so this Fiddle gets it a little better, I think:

var variants = function(amount, chars) {
    var soFar = arguments[2] || [""];
    // ... no other changes.
}

Upvotes: 1

scrappedcola
scrappedcola

Reputation: 10572

Your issue is that you never hit your exit clause and you are getting an infinite recursion. Your issue lies here:

var newjunk;
...
variants(amount, chars, junk+newjunk+chars[i]);

You do not initialize newjunk to anything and so when it skips over the part that has a chance of setting it your variable remains undefined. So when you go to concatenate the string to the other variables in your else clause, what is happening is js is converting the value "undefined" to a string of "undefined". For a test cut-n-paste this line:

var newjunk; var junk = ""; var chars = ["1","2"]; console.log(result, junk+newjunk+chars[0]); 

into your favorite console. Notice it prints out undefined1. The way to fix it is to init newjunk to an empty string:

var newjunk = ""

Here is a jsfiddle of the change.

A good way to debug recursion issues is to break out a piece of paper and pen and physically trace through each line of the code, to ensure that your exit clause is hit. You can also add a premature exit condition, in the form of a global count variable, that you increment inside your function. When this count variable hits a specific value, exit.

Upvotes: 3

Related Questions