javascript permutation generator with permutation length parameter

后端 未结 4 1056
鱼传尺愫
鱼传尺愫 2020-12-05 22:45

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 t

相关标签:
4条回答
  • 2020-12-05 23:04

    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:

    0 讨论(0)
  • 2020-12-05 23:08

    A little late, but maybe this will help somebody. It allows for repetition, and length specification :)

    function samplePermutation(sequence, repetition = false, n = null) {
      if (sequence.constructor !== Array) {
        throw new Error("samplePermutation: sequence needs to be an array.");
      }
    
      if (n === null) {
        n = sequence.length;
      } 
    
      var permutation = [];
      var add;
      while ((repetition && (permutation.length < n)) || ((!repetition) && (sequence.length))) {
        var index = Math.floor(Math.random() * sequence.length);
        if (repetition) {
          add = sequence[index];
        } else {
          add = sequence.splice(index, 1);
        }
        permutation = permutation.concat(add);
      }
    
      return (permutation);
    }
    
    0 讨论(0)
  • 2020-12-05 23:10

    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

    0 讨论(0)
  • 2020-12-05 23:12

    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 讨论(0)
提交回复
热议问题