let someChars = ['A', 'B', 'C', 'D']; /** * Handle all permutations for one array item (in relation to all other array items) */ function permutateAgainstOneItem(arr) { let [first, ...tail] = arr; let head = [first]; let permutations = []; const reduceTail = function () { return tail.reduce((acc, char, i) => { // fix the char to the left head.push(char); tail.splice(i, 1); // console.log(head, tail); // only push to the permutation array if we've arrived recursively // at the end of the tail array (so no dupes!) if (tail.length === 1) acc.push([...head, ...tail].join('')); // reduce recursively as long as the tail more than one item left if (tail.length > 1) reduceTail(); // as you were... head.pop(); tail.splice(i, 0, char); return acc; }, permutations); } reduceTail(arr); return permutations; } /** * Produces all char permutations for all items in the array */ function permutateArray(chars) { const allPermutations = chars.reduce((acc, curr, i, arr) => { const charPermutations = permutateAgainstOneItem(arr); acc.push(...charPermutations); // take first item off the arr and move it to the back const first = arr.shift(); arr.push(first); return acc; }, []); // Remove dupes! return [...new Set(allPermutations)]; } console.log(permutateArray(someChars));