Search code examples
javascriptnode.jsarraysjavascript-objectsshuffle

Javacript: Is there a function that shuffles an array with every element switching places?


I'm looking for a function that, instead of simply shuffling an array, shuffles it without any element being left at the index he was previously in.

I've tried the Fisher-Yates algorithm, but it didn't solve my problem:

function shuffle(array) {
  var m = array.length, t, i;
  while (m) {
    i = Math.floor(Math.random() * m--);
    t = array[m];
    array[m] = array[i];
    array[i] = t;
  }
}

When testing, I've got results like [0, 1, 2, 3, 4, 5] shuffling into [5, 0, 3, 1, 4, 2]. But here, 4 pretty much "stayed" at the same index it previously was.

The function I'm looking for would for example randomize [0, 1, 2, 3, 4, 5] into [4, 1, 5, 3, 2] where no element is at the same index it were previously


Solution

  • Check that the element being put into the rightmost (first unsorted) position isn't the same as what was there originally. You'll also need to make sure that what gets inserted on the final swap doesn't result in an infinite loop - use a separate condition for that after the loop is over.

    function shuffle(array) {
      const originalArray = [...array];
      let m = array.length;
      while (m > 1) {
        let i;
        do {
          i = Math.floor(Math.random() * m);
        } while (array[i] === originalArray[m - 1]);
        m--;
        const t = array[m];
        array[m] = array[i];
        array[i] = t;
      }
      if (array[0] === originalArray[0]) {
        [array[0], [array[1]]] = [array[1], [array[0]]];
      }
      return array;
    }
    for (let i = 0; i < 100; i++) {
      console.log(shuffle([0, 1, 2, 3, 4, 5]));
    }