0

As shown at https://jsfiddle.net/LBMF_1/gacLzLnn/, I have code that ostensibly generates all the possible permutations of 8 digits, using for loops within for loops.(At end of question) My code seems to be correct in syntax, as both JSHint and the in-chrome console are free of errors. Is this my error, or is this a common problem caused by JS? It's probably the former as it seems that this should work Bonus Points: What other ways could be used to avoid the nested for loops? You don't know how much I am thankful for any help. Also, what is up with Stack Overflow and new paragraphs? The code is here, and it appears to me that when run should stick a really long list of numbers in the console, but instead lots of "undefined"'s appear.

var generator = function() {
  listofavailable = listofavailablereset;
  fullarray = [];


  for (i = 7; i > 0; i--) {
    numgen = "";
    inum = listofavailable[i];
    listofavailable.splice(i, 1);
    numgen = inum;
    for (v = 6; v > 0; v--) {
      vnum = listofavailable[v];
      listofavailable.splice(v, 1);
      numgen = numgen.concat(vnum);
      console.log(numgen);
      for (c = 5; c > 0; c--) {
        cnum = listofavailable[c];
        listofavailable.splice(c, 1);
        numgen = numgen.concat(cnum);
        for (g = 4; g > 0; g--) {
          gnum = listofavailable[g];
          listofavailable.splice(g, 1);
          numgen = numgen.concat(gnum);
          for (k = 3; k > 0; k--) {
            knum = listofavailable[k];
            listofavailable.splice(k, 1);
            numgen = numgen.concat(knum);
            for (b = 2; b > 0; b--) {
              bnum = listofavailable[b];
              listofavailable.splice(b, 1);
              numgen = numgen.concat(bnum);
              for (j = 1; j > 0; j--) {
                jnum = listofavailable[j];
                listofavailable.splice(j, 1);
                numgen = numgen.concat(jnum);
                fullarray = fullarray + numgen;
              }
            }
          }
        }
      }
    }
  }

};
LBMF_1
  • 17
  • 7
  • 4
    Have you considered refactoring to anything more readable? – Luka Jacobowitz Mar 16 '16 at 00:16
  • I don't think the problem has anything to do with `for` loops. The problem is that `numgen` is `undefined` at some point when you're trying to `.concat()` to it. – Pointy Mar 16 '16 at 00:18
  • see this http://stackoverflow.com/questions/9960908/permutations-in-javascript for a better way to generate permutations – gabesoft Mar 16 '16 at 00:27

2 Answers2

0

Here's a modified implementation based on your fiddle. Note that the digits '0' and '5' are missing from your example, I'm not sure if this is intended.

var listofavailable = ['1', '2', '3', '4', '6', '7', '8', '9'];
var fullarray;

var generator = function() {
  fullarray = [];
  var numgen;
  // first digit
  for (var a = 7; a >= 0; a--) {
    var anum = listofavailable[a];
    listofavailable.splice(a, 1);
    numgen = anum;
    // second digit
    for (var i = 6; i >= 0; i--) {
      var inum = listofavailable[i];
      listofavailable.splice(i, 1);
      numgen = numgen.concat(inum);
      // third digit
      for (var v = 5; v >= 0; v--) {
        var vnum = listofavailable[v];
        listofavailable.splice(v, 1);
        numgen = numgen.concat(vnum);
        // fourth digit
        for (var c = 4; c >= 0; c--) {
          var cnum = listofavailable[c];
          listofavailable.splice(c, 1);
          numgen = numgen.concat(cnum);
          // fifth digit
          for (var g = 3; g >= 0; g--) {
            var gnum = listofavailable[g];
            listofavailable.splice(g, 1);
            numgen = numgen.concat(gnum);
            // sixth digit
            for (var k = 2; k >= 0; k--) {
              var knum = listofavailable[k];
              listofavailable.splice(k, 1);
              numgen = numgen.concat(knum);
              // seventh digit
              for (var b = 1; b >= 0; b--) {
                var bnum = listofavailable[b];
                listofavailable.splice(b, 1);
                numgen = numgen.concat(bnum);

                // eighth digit
                //add whatever else is left in listofavailable[0] to the string
                var jnum = listofavailable[0];
                numgen = numgen.concat(jnum);

                fullarray.push(numgen);
                //console.log(numgen);

                //revert list removals
                listofavailable.push(numgen.substr(numgen.length - 2,1));

                //revert additions to the string
                numgen = numgen.substr(0,numgen.length-2);
              }// b loop
              listofavailable.push(numgen.substr(numgen.length - 1));
              numgen = numgen.substr(0,numgen.length-1);
            }// k loop
            listofavailable.push(numgen.substr(numgen.length - 1));
            numgen = numgen.substr(0,numgen.length-1);
          }// g loop
          listofavailable.push(numgen.substr(numgen.length - 1));
          numgen = numgen.substr(0,numgen.length-1);
        }// c loop
        listofavailable.push(numgen.substr(numgen.length - 1));
        numgen = numgen.substr(0,numgen.length-1);
      }// v loop
      listofavailable.push(numgen.substr(numgen.length - 1));
      numgen = numgen.substr(0,numgen.length-1);
    } // i loop
    listofavailable.push(numgen.substr(numgen));
    numgen = "";
  } // a loop
};
generator();

console.log(fullarray.length);
console.log(fullarray);

To explain what was wrong with the original code.

You are getting an undefined on the second iteration of the b loop

              bnum = listofavailable[b];

this is because your function was emptying out the array of 7 available values, each time it splices out a value, leaving listofavailable as a single element array, listofavailable[0] = "1". However, when b iterates the second time it is trying to get the element listofavailable[1] which doesn't exist, hence bnum = undefined. When trying to concatenate the undefined value to numgen this then makes numgen = undefined and breaks everything afterwards.

Additionally, the way you're trying to add to an array

fullarray = fullarray + numgen;

doesn't perform how you're intending, you're actually looking for the Array.prototype.push() function, so it would be

fullarray.push(numgen);

and using a reset value for the listofavailable is a good idea, but the way you've implemented it also won't work as

listofavailable = listofavailablereset;

doesn't copy the array elements from listofavailablereset into listofavailable but it just makes listofavailable reference the same array object, hence when you modify one, you're affecting the other. Instead you can just copy your array over using slice() eg.

listofavailable = listofavailablereset.slice();

Note that slice() only creates a shallow copy, object references within each array will both point to the same object.

Check out the Mozilla Javascript Reference pages for excellent javascript reference documentation.

Kiz
  • 429
  • 5
  • 14
  • I get all the fixes except the first one, could you explain it a little bit? If the array was empty, why would it have the value of 1? – LBMF_1 Mar 16 '16 at 12:48
  • Have fixed the code and tried to explain better what the issue was – Kiz Mar 16 '16 at 21:43
  • Great! Thank you so much! – LBMF_1 Mar 16 '16 at 22:39
  • Hmm. I get what I was doing wrong, and I reallllly appreciate the answer. However, when I take the 0 and 5 out of there(supposed to be out, sorry for not stating that), it returns an array with a length of 35280, when I'm pretty sure it should be 8!, or 40320. Also, the individual values have repeated digits, which is what I was trying to avoid with the splicing in the original one. – LBMF_1 Mar 16 '16 at 22:44
  • Thanks! :-) Really appreciate the help! – LBMF_1 Mar 16 '16 at 23:13
0

What you're doing by generating these permutations is isomorphic to enumerating all of the 8-digit base 8 numbers, so just do that:

var digits = ['1', '2', '3', '4', '6', '7', '8', '9'];
var n, d, permutations = [], entry;

for (var i = 0, limit = parseInt("100000000", 8); i < limit; ++i) {
  entry = "";
  for (d = 0, n = i; d < digits.length; ++d) {
    entry = digits[n % 8] + entry;
    n = Math.floor(n / 8);
  }
  permutations.push(entry);
}
console.log(permutations);

Note that this will take a long time. Your browser (if you're doing it in a browser) will complain about a busy script.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Shouldn't the resulting array have a length of 8!, or 40320? This seems like a decently sized array for JS to handle. If not, why? – LBMF_1 Mar 16 '16 at 12:15
  • @LBMF_1 it depends - are you intending that the digits can be *re-used* - so, is 11111111 one of the values you want? If not, then this method I wrote won't work. – Pointy Mar 16 '16 at 13:02
  • I was intending for the splice to remove the digit so it will not repeat. How much would this change your method? – LBMF_1 Mar 16 '16 at 17:05