0

I'm trying to display elements from an array on a site built with React, but randomized so that whenever people come to the site, they see a randomized element of the array. Right now, I use a simple random index:

const randomIndex = keys[Math.floor(Math.random() * keys.length)];

to get a randomized element in the array. However, I want to be able to evenly present elements randomly (basically like Qualtrics' Randomizer: Evenly Present Elements function. Essentially, I want to ensure that each of the array elements is roughly presented a equal number of times across all site visitors. Essentially, I want to make sure that my array randomizer doesn't reset every time another site visitor comes to the site, so that across all different site visitors, there is a uniform distribution of array elements shown.

Does anyone have any idea how to do that in React? Thank you so much!

Anonymous
  • 239
  • 4
  • 16
  • 1
    Does this answer your question? [Generating uniform distribution using Math.random()](https://stackoverflow.com/questions/26795084/generating-uniform-distribution-using-math-random) – Nicholas Carey Jan 20 '21 at 21:45
  • The one thing I might suggest is to use a better PRNG than `Math.random()`. The Mersenne Twister is a pretty decent algorithm. And there's an implementation available on NPM: https://www.npmjs.com/package/mersenne-twister – Nicholas Carey Jan 20 '21 at 21:48
  • @NicholasCarey The question you linked seems to me that the OP was mis-counting the results and doesn't really address either how to get a uniform distribution or how to make sure all elements are used prior to repeating. I'd say https://stackoverflow.com/q/2450954/17300 is closer to this question. – Stephen P Jan 22 '21 at 00:07
  • @StephenP — I can buy that. The question in the O.P. is lacking in specifics. Are they displaying a single item from the array, the entire array, or a subset of the array? The entire array or a subset of the array? But shuffling the entire array would work for all of those cases. Shuffle and take the first N items. Just computationally more expensive if you just need a single item. – Nicholas Carey Jan 22 '21 at 00:52

1 Answers1

1

Having even distribution is the definition of random, as demonstrated:

const iterations = 10000;
const max = 10;
const getRandom = () => Math.floor(Math.random() * max);

const results = Array(max).fill(0);
for (let i = 0; i < iterations; i++) {
  results[getRandom()] += 1;
}

function getVariance(arr) {
  const mean = arr.reduce((sum, x) => sum + x) / arr.length;
  return arr.reduce((acc, x) => Math.pow(x - mean, 2)) / arr.length;
}
const variance = getVariance(results);

const wrapper = document.getElementById('wrapper');
results.forEach((result) => {
  const column = document.createElement('div');
  column.classList.add('column');
  column.style.height = `${result / 10}px`;
  column.innerHTML = result;
  wrapper.appendChild(column);
});

document.getElementById('variance').innerHTML = `The variance is: ${variance} (With ${iterations} iterations)`;
#wrapper {
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.column {
  background-color: tomato;
  color: white;
  width: 40px;
  margin: 2px;
  text-align: center;
}
The following is a histogram of <code>Math.random()</code> results:
<div id="wrapper"></div>
<div id="variance"></div>
GalAbra
  • 5,048
  • 4
  • 23
  • 42
  • Ah thank you for this super helpful visual -- to clarify, I guess my biggest question is: how does this Math.random uniform distribution work when different people come to my React site? Each time someone new, comes to my site, I want them to see a different random thing so that at the end, across all of my site visitors, there is a uniform distribution of what random element they saw. Thanks so much! – Anonymous Jan 21 '21 at 18:02
  • 1
    @Anonymous — as GalAbra shows Math.random() is uniformly distributed and is "good enough" for most purposes, and I expect good enough for your goal. Your site visitors will get a roughly even distribution of what they see without you going to extra lengths, just as a natural consequence of the randomness. A different but somewhat related strategy is being random but making sure everything is used before repeating. That is done by shuffling an array of the possibilities, like a deck of cards, then using the random array in sequence. But that would require remembering the array server-side. – Stephen P Jan 22 '21 at 00:14