0

Possible Duplicate:
How to randomize a javascript array?

I am writing a code in JavaScript in which I need to take 35 input values, assign each of them a place in an array, then shuffle them such that they will be rearranged in a different order. As such:

var sort = new Array(35);
sort[0] = document.getElementById("d1p1").value;
sort[1] = document.getElementById("d1p2").value;
// ...
// ... (till 35)
var rand1 = Math.floor(Math.random() * 35);
var rand2 = Math.floor(Math.random() * 35);
// ...
// ... (till 35)
var rsort = new Array(35);
rsort[rand1] = document.getElementById("d1p1").value;
rsort[rand2] = document.getElementById("d1p2").value;

The only problem is that since Math.floor(Math.random()*35) generates some of the same numbers from 1-35 more than once (well, I guess that is the point of randomness), then two values are sometimes assigned the same input box and they return undefined. Any ideas?

Community
  • 1
  • 1
Daccache
  • 125
  • 2
  • 8

2 Answers2

8

What you should do in order to generate a uniform distribution of values in your random permutation is do it like this:

  • pick a random index from 0 to 35, and swap the first value with that index
  • then pick another random index from 1 to 35 and swap the second value with that index
  • continue on like so for all the remaining indices (2 - 35)

Here's a potential implementation:

 // first make a copy of the original sort array
 var rsort = new Array(sort.length);
 for(var idx = 0; idx < sort.length; idx++)
 {
     rsort[idx] = sort[idx];
 }

 // then proceed to shuffle the rsort array      
 for(var idx = 0; idx < rsort.length; idx++)
 {
    var swpIdx = idx + Math.floor(Math.random() * (rsort.length - idx));
    // now swap elements at idx and swpIdx
    var tmp = rsort[idx];
    rsort[idx] = rsort[swpIdx];
    rsort[swpIdx] = tmp;
 }
 // here rsort[] will have been randomly shuffled (permuted)

I hope this helps.

Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
0

You can use this little function adapted from this other answer. Also I would use a class so it's easier to grab all your inputs.

function randomArray(min, max) {
  return (new Array(max-min))
    .join(',').split(',')
    .map(function(v,i){ return [Math.random(), min + i]; })
    .sort().map(function(v) { return v[1]; });
}

var inputs = document.querySelectorAll('.myinput');

// Creates an array with all your input elements in random order
var randomInputs = randomArray(0, inputs.length).map(function(n){
  return inputs[ n ];
});

Demo: http://jsbin.com/uyaqed/1/edit (ctrl+enter to refresh)

Community
  • 1
  • 1
elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • This is a bad way to random shuffling, it's both inefficient (shuffling is easier than sorting) and incorrect (the comparison function should be consistent with a total ordering of the elements). – 6502 Dec 25 '12 at 19:17
  • Mmm... Can't see why this a bad way and incorrect.. It works fine, and I've used it before in other projects and does the job. – elclanrs Dec 25 '12 at 19:22
  • @6502: Check demo here http://jsbin.com/uyaqed/1/edit – elclanrs Dec 25 '12 at 19:26
  • Sorry, I got confused while following the links. This algorithm is bad (like I said sorting is harder than shuffling) but not incorrect if we assume infinite precision for `Math.random` (that assumption is however the best reasonable approximation in Javascript). Removed the downvote. Note however that "works" doesn't mean that you sometimes saw it producing results that you thought were correct. – 6502 Dec 25 '12 at 19:41
  • @6502: I see what you mean. Randomness is subjective to the eye though, "accurate" randomness is hard to achieve but this should work just fine for most things; it "looks" random. I made that script for [this plugin](http://elclanrs.github.com/jq-tiles/) and it works very well to create the "random" tiles effect. – elclanrs Dec 25 '12 at 19:58