Given a list of N objects, how do I make 2N selections in a random order such that no object is chosen twice in succession? (All N objects must be chosen twice.)
EDIT start: My goal is to present a list of words, once on the left and once on the right. No two consecutive trials are to have the same word.
Really I am asking if there is a known technique for doing this, or can someone think of a way to do it without the fiddle. EDIT end
My attempt is shown below, and may be useful as a template for testing.
The premise is to generate randomised indices and then check for repeats. When a repetition is found, swap the first repetition with the value before. Finally, if the lower two elements are the same, swap the 2nd and 3rd.
<script type="text/javascript">
function init() {
for (rep = 0; rep < 100000; rep++) {
var indices = [0,0, 1,1, 2,2];
shuffle(indices);
for (var i = indices.length - 1; i > 1; i--)
if (indices[i - 1] == indices[i]) {
var tmp = indices[i - 1];
indices[i - 1] = indices[i - 2];
indices[i - 2] = tmp;
}
if (indices[0] == indices[1]) {
var tmp = indices[1];
indices[1] = indices[2];
indices[2] = tmp;
}
// test
for (i = indices.length - 1; i > 1; i--)
if (indices[i - 1] == indices[i])
rep = 1E8; // fail
}
// **EDIT2:** BAD BAD BAD mistake in the check code!!! Sorry!
dbg.innerHTML = (rep >= 1E8) ? "Oh bother." : "OK";
}
function randomInt(max) { return Math.floor(Math.random() * max); }
function shuffle(o) { for (var j, x, i = o.length; i; j = randomInt(i), x = o[--i], o[i] = o[j], o[j] = x); return o; }
</script>
<div>
<span id="dbg" />
</div>
The failure of the method to deal with the lowest two elements is common to the alternative method of selecting from a reducing list. One potentially ends up with two identical elements remaining.
(Note, the method presented is not recommended for use since may not have a uniform random distribution.)
EDIT start: The experiment is supposed to present words in a "random" order. My method below has a 'fiddle' with the last two numbers just seems wrong - at the very least nasty.
(I agree that the overall sequence is not truly random. I am not a mathematician, just trying to code the experiment.) EDIT end
(Shuffle code taken from Jeff's answer.)