1

I'm trying to write a function that would return all permutations of a given array of numbers, as in the examples below:

a = [1, 1, 2]
permutator(a) = [
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

b = [2, 3, 4]
permutator(b) = [
  [2,3,4],
  [2,4,3],
  [3,2,4],
  [3,4,2],
  [4,2,3],
  [4,3,2]
]

order of the results isn't accurate

Can you explain why the code below doesn't work? I tried debugging and I think the variables temp and result aren't being kept in memory as arrays but I'm not sure if that is the case nor how to solve it.

permutator = (array) => {
  const result = [];

  array.forEach((num, i) => {
    array.forEach((num2, j) => {
      if (i !== j) {
        let temp = array;
        temp[i] = temp[j];
        temp[j] = num;
        console.log(`temp: ${temp}`);
        console.log(`result: ${result}`);
        if (!result.includes(temp)) result.push(temp);
        console.log(`result: ${result}`);
      }
    });
  });

  return result;
}

as you can see I tried console.logging everything to no avail...

Marcos
  • 1,043
  • 10
  • 15
  • Instead of `console.log` use please `debugger` keyword and also see some videos on how to debug javascript code using `debugger` keyword? – palaѕн Apr 02 '20 at 18:03
  • I was using VS Code to debug so console.log was just desperation on my part to try to see what was going on but thanks anyway! – Marcos Apr 02 '20 at 18:33
  • 1
    a) arrays are assigned by reference. If you expect to make a copy, [you need to do it explicitly](https://stackoverflow.com/q/7486085/1048572) b) `result.includes(temp)` will compare the `result` elements by reference as well c) this doesn't look like an algorithm for creating permutations at all – Bergi Apr 02 '20 at 19:19
  • Thanks @Bergi! Just changing this line of code: "let temp = array;" to "let temp = array.slice();" made the algorithm work. If you have the time can you explain to me why it doesn't seem like an algorithm for creating permutations, please? I imagine it isn't the most efficient but it works. – Marcos Apr 05 '20 at 12:02
  • @MarcosCannabrava I guess it only works for arrays of length 3. For a general solution, you normally would use recursion. See [this topic](https://stackoverflow.com/q/9960908/1048572) for solutions. – Bergi Apr 05 '20 at 13:24

2 Answers2

1

This works for three digits, but I wouldn't call it elegant:

let indexAtEachPosition = function (ind, arr) {
  let arrayGroup = [];
  let arrLength = arr.length;
  let movedArray = [...arr];
  for (let indx = 0; indx < arrLength; indx++) {
    let firstItem = movedArray[0];
    let otherItems = movedArray.slice(1);
    otherItems[arrLength - 1] = firstItem
    movedArray = [...otherItems];
    arrayGroup.push(movedArray.join(" "));
  }
  return arrayGroup;
}

let permutator = function permutator(values) {
  let returnValue = new Set();
  let digitCount = values.length;
  returnValue.add(values.join(" "));

  values.forEach(digit => {
    indexAtEachPosition(digit, values).forEach(variation => {
      returnValue.add(variation);
    });
  });
  [...values.reverse()].forEach(digit => {
    indexAtEachPosition(digit, values).forEach(variation => {
      returnValue.add(variation);
    });
  });
  return [...returnValue].map(eachArr => {
    return eachArr.split(" ");
  });
};



// console.log( permutator([0,0,0]) );
// console.log( permutator([1,0,0]) );
// console.log( permutator([1,2,3]) );
console.log( permutator([1,1,2]) );
console.log( permutator([2,3,4]) );

I'm not sure what the goal of this is, but it intrigued me like some kind of code test so I tried to solve it.

Jason Lydon
  • 7,074
  • 1
  • 35
  • 43
  • If you're looking for an elegant solution, maybe something like [this](https://stackoverflow.com/a/57084205/1048572)? – Bergi Apr 05 '20 at 13:23
0

This answer is the most elegant solution I found.

const permutator = (inputArr) => {
  let result = [];

  const permute = (arr, m = []) => {
    if (arr.length === 0) {
      result.push(m)
    } else {
      for (let i = 0; i < arr.length; i++) {
        let curr = arr.slice();
        let next = curr.splice(i, 1);
        permute(curr.slice(), m.concat(next))
      }
    }
  }

  permute(inputArr)

  return result;
}

console.log(permutator([1,2,3]));
Marcos
  • 1,043
  • 10
  • 15