Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decrease the probability of getting random item from array same as previous one

Say, I've got an array like

var arr = [1,2,3,4,5,6,7,8,9,10,11,12];

and I wanna get random array item, but later I would like to re-randomize my current item. What is the efficient way to exclude or reduce the chance of getting the same item once again?

Does stuff like this really help:

current != arr[Math.floor(Math.random() * 12)] ? current = arr[Math.floor(Math.random() * 12)] : arr[Math.floor(Math.random() * 12)];

I mean, would it recalculate random array index each time or just link to the same value? What is a better way?

like image 409
Tristan Tzara Avatar asked Jul 21 '26 22:07

Tristan Tzara


2 Answers

If you can keep array unsorted: (if not, you can use array which only contains indices of elements in first array)

var array = [ ... ];
var len = array.length;

function getRandomItem(){
    if (len <= 0) len = array.length;
    var item = Math.floor(Math.random()*len--);
    var x = array[item];
    array[item] = array[len];
    array[len] = x;
    return array[len];
}

Idea behind is to exclude already dispatched items by placing them outside of item fetching range. Function getRandomItem() will not return same item twice until all other elements also will be returned.


Following modification will only prevent function to return same element which was returned during previous call, as requested.

var array = [ 3, 1, 4, 5, 9, 2, 6, 8, 7 ];
var len = array.length-1;

function getRandomItem(){
    if (len == 0) return array[0];
    var item = Math.floor(Math.random()*len);
    var x = array[item];
    array[item] = array[len];
    array[len] = x;
    return array[len];
}

document.write("Starting array: " + array + "<br/>");
document.write("Selected value: " + getRandomItem() + "<br/>");
document.write("Resulting array: " + array);

Also see Fisher–Yates shuffle

like image 198
weaknespase Avatar answered Jul 24 '26 14:07

weaknespase


I think the best solution is to put a while loop to check if the value is similar to the previous one or not.

var arr = [1,2,3,4,5,6,7,8,9,10,11,12];

Then you write:

   var last_generated_value = null;
   var val = Math.random();
   val = Math.floor(val * 12);

   while(last_generated_val == val)
   {
       val = Math.random();
       val = Math.floor(val * 12);
   }

   last_generated_value = val;

Though you may put the above code block in a parent loop or a function to generate a concatenated set of values(in your case, number).

like image 36
Mostafa Talebi Avatar answered Jul 24 '26 12:07

Mostafa Talebi