最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

node.js - javascript permutation generator with permutation length parameter - Stack Overflow

programmeradmin2浏览0评论

I've seen a few generators out there but they all make a squared matrix. For example, you give it a list of three items and it'll assume the output of the length is also three. However, I'd like to specify the items and the length.

Sound like an easy problem can't believe there isn't a library available for it. Would like to avoid writing this myself if there's a tested library out there. Any suggestions would be great.

Example of what i've found

var list = 'abc';
perms = permutations(list);
//you cannot define the length

Example

var list = 'abc';
var length = 3;

perms = permutations(list,length);

console.log(perms);

/* output
a,a,a
a,b,c
a,b,a
a,c,a
c,a,a
...
*/

I would like to be able to change length and should create permutations accordingly

length = 2

a,a
a,b
b,b
b,a

length = 4

a,a,a,a 
a,a,a,b
....

I've seen a few generators out there but they all make a squared matrix. For example, you give it a list of three items and it'll assume the output of the length is also three. However, I'd like to specify the items and the length.

Sound like an easy problem can't believe there isn't a library available for it. Would like to avoid writing this myself if there's a tested library out there. Any suggestions would be great.

Example of what i've found

var list = 'abc';
perms = permutations(list);
//you cannot define the length

Example

var list = 'abc';
var length = 3;

perms = permutations(list,length);

console.log(perms);

/* output
a,a,a
a,b,c
a,b,a
a,c,a
c,a,a
...
*/

I would like to be able to change length and should create permutations accordingly

length = 2

a,a
a,b
b,b
b,a

length = 4

a,a,a,a 
a,a,a,b
....
Share Improve this question edited Apr 26, 2014 at 2:53 uptownhr asked Apr 26, 2014 at 2:01 uptownhruptownhr 6726 silver badges15 bronze badges 9
  • 2 What have you done so far? – Praveen Kumar Purushothaman Commented Apr 26, 2014 at 2:03
  • I found an npm module combination_gen that generates combinations in this way but doesn't support permutations. Before that I tried to write my own by looping through the list but found that it was more difficult than it looks. – uptownhr Commented Apr 26, 2014 at 2:06
  • what do you mean by length ? – ProllyGeek Commented Apr 26, 2014 at 2:09
  • Is it possible to check out that code? – Praveen Kumar Purushothaman Commented Apr 26, 2014 at 2:09
  • @ProllyGeek He means the length of the generated permutation. – Praveen Kumar Purushothaman Commented Apr 26, 2014 at 2:09
 |  Show 4 more comments

3 Answers 3

Reset to default 11

You can imagine the length as representing the number of slots. Each slot has N possibilities, given that N is the number of elements in your initial list. So given three values [1,2,3], you will have a total of 3 x 3 x 3 = 27 permutations.

Here's my attempt. Comments included!

var list = [1,2,3];

var getPermutations = function(list, maxLen) {
    // Copy initial values as arrays
    var perm = list.map(function(val) {
        return [val];
    });
    // Our permutation generator
    var generate = function(perm, maxLen, currLen) {
        // Reached desired length
        if (currLen === maxLen) {
            return perm;
        }
        // For each existing permutation
        for (var i = 0, len = perm.length; i < len; i++) {
            var currPerm = perm.shift();
            // Create new permutation
            for (var k = 0; k < list.length; k++) {
                perm.push(currPerm.concat(list[k]));
            }
        }
        // Recurse
        return generate(perm, maxLen, currLen + 1);
    };
    // Start with size 1 because of initial values
    return generate(perm, maxLen, 1);
};

var res = getPermutations(list, 3);
console.log(res);
console.log(res.length); // 27

fiddle

If you're looking for an answer based on performance, you can use the length of the array as a numerical base, and access the elements in the array based on this base, essentially replacing actual values from the base with the values in your array, and accessing each of the values in order, using a counter:

const getCombos = (arr, len) => {
  const base = arr.length
  const counter = Array(len).fill(base === 1 ? arr[0] : 0)
  if (base === 1) return [counter]
  const combos = []
  const increment = i => {
    if (counter[i] === base - 1) {
      counter[i] = 0
      increment(i - 1)
    } else {
      counter[i]++
    }
  }

  for (let i = base ** len; i--;) {
    const combo = []
    for (let j = 0; j < counter.length; j++) {
      combo.push(arr[counter[j]])
    }
    combos.push(combo)
    increment(counter.length - 1)
  }

  return combos
}

const combos = getCombos([1, 2, 3], 3)
console.log(combos)

For smaller use cases, like the example above, performance shouldn't be an issue, but if you were to increase the size of the given array from 3 to 10, and the length from 3 to 5, you have already moved from 27 (33) combinations to 100,000 (105), you can see the performance difference here:

I wrote a little library that uses generators to give you permutations with custom items and number of elements. https://github.com/acarl005/generatorics

const G = require('generatorics')

for (let perm of G.permutation(['a', 'b', 'c'], 2)) {
  console.log(perm);
}
// [ 'a', 'b' ]
// [ 'a', 'c' ]
// [ 'b', 'a' ]
// [ 'b', 'c' ]
// [ 'c', 'a' ]
// [ 'c', 'b' ]
发布评论

评论列表(0)

  1. 暂无评论