Characters set permutations with repetitions The code bellow generates all the permutation(with repetitions) for given character set. Is there any better(simpler, more performant) way to do that?

var assert = require('chai').assert
var _ = require('underscore')

var multStr = function(left, rigth) {
  return _.chain(left).map(function(el) {
    return _(rigth).map(function(chr) {
      return el + chr
    })
  })
  .flatten()
  .value()
}

function solution(space, len) {
  return _.chain(
      _(len - 1).range()
    )
    .reduce(
      function(acc, next) {
          acc.push(
            multStr(
              _.last(
                acc
              ),
              space
            )
          )
          return acc
      },
      [space.split('')]
    )
    .flatten()
    .value()
}

assert.deepEqual(multStr(['ab'], 'ab'), ['aba', 'abb'])
assert.deepEqual(solution('abc', 1), ['a', 'b', 'c'])
assert.deepEqual(solution('a', 2), ['a', 'aa'])
assert.deepEqual(solution('ab', 2), ['a', 'b', 'aa', 'ab', 'ba', 'bb'])
assert.deepEqual(solution('abc', 3), [ 'a', 'b', 'c',
  'aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc',
  'aaa', 'aab', 'aac', 'aba', 'abb', 'abc', 'aca', 'acb', 'acc',
  'baa', 'bab', 'bac', 'bba', 'bbb', 'bbc', 'bca', 'bcb', 'bcc',
  'caa', 'cab', 'cac', 'cba', 'cbb', 'cbc', 'cca', 'ccb', 'ccc'
])
I think the code and the approach look good overall. I have just a few comments:

1) The indentation makes it a bit hard to read. A line like:

acc.push(multStr(_.last(acc), space))


Reads better than across many lines in my opinion.

2) You may consider using concat instead of push:

return acc.concat(multStr(_.last(acc), space))


You trade a bit of performance for it though as concat creates a new array.

3) The most notable problem I see with your code is that it is not very reusable. It only works for strings, while the idea and implementation certainly apply to arrays too. We can think of a string as an array of characters, so abstracting for arrays makes the code more reusable, since we can then do the string one trivially with str.split('').

This leads to the name of the function multStr; it is too specific, and hungarian notation means you are probably over-specifying its functionality, it ought to be more abstract.

Intuitively you wrote code that is more abstract than it seems. I find the Haskell equivalent to your code quite elegant and concise, almost by accident:

[1..3] &gt;&gt;= \n -&gt; replicateM n "ab"


The concept at hand is very general: lists are monads.

We can replicate this in JavaScript easily with lodash. We need flatMap, and range:

var {flatMap, range} = require('lodash')


Next we can loosely translate the Haskell implementations of replicateM and sequence to build combinations:

function combinations(n, xs) {
  return flatMap(range(1, n + 1), m =&gt; replicateM(m, xs))
}

function replicateM(n, x) {
  return sequence(Array(n).fill(x))
}

function sequence(ms) {
  return ms.reduce((ma, mb) =&gt; {
    return flatMap(ma, a =&gt; mb.map(b =&gt; a.concat(b)))
  }, [[]])
}


Now this is already more general, we pass an array of characters and get an array of arrays of characters that represent all the possible combinations of n length.

To make it work for your case you only need to split then join:

combinations(3, 'ab'.split('')).map(cs =&gt; cs.join(''))
/*^
[ 'a', 'b',
  'aa', 'ab', 'ba', 'bb',
  'aaa', 'aab', 'aba', 'abb',
  'baa', 'bab', 'bba', 'bbb'
]
*/