<!-- You can't know whether I'm exploiting a bias in the crappy JS -->
<!-- RNG to make my name first more often. Hah-hah. -->
document.addEventListener("DOMContentLoaded", function(event) {
var names = ["Erin Ptacek", "Thomas Ptacek", "Jeremy Rauch"].
sort(function(x, y) { return 1 - Math.ceil(Math.random() * 100) % 3; });
for(var i = 0; i < 3; i++) {
document.getElementById("n_" + i).textContent = names[i];
}
});
It isn't scientific in the slightest, but I ran the function a hundred million times, and Erin seems to appear first about 60% of the time, in Google Chrome.
Good luck with the company, I hope you can also beat the RNG that makes or breaks a startup :)
Ah, I think I've figured it out (nothing to do with JS's RNG, sadly). It's simpler when you ignore Jeremy (sorry). For this case, we can assume `Math.random()` will output uniformly random numbers. `Array.prototype.sort` works as so:
If the function returns > 0, the first param should be sorted to a higher index than the second.
If the function returns < 0, the first param should be sorted to a lower index than the second.
If the function returns exactly zero, the parameters are left as they are.
So what we've got is a 1/3 of Erin 'winning', 1/3 of Thomas 'winning' and a 1/3 chance of a tie which leaves Erin ahead. So she's got a 2/3 chance of being first.
Additionally (but not in any consequential fashion), generating a random number between 1 and 100 (inclusive) gives you 100 possibilities (duh). With three outcomes:
100 / 3 = 33.333333333333336
The first option has slightly more chance to be picked. If Erin wanted to be fair(er), she'd multiply by 99.
Here's a Python solution showing it's not just JS:
This implicitly assumes that Array.sort is stable: that is, if the comparison function returns 0 then sorting leaves the array elements in their original relative positions. That's not guaranteed by the JavaScript specification, see e.g. https://bugs.chromium.org/p/v8/issues/detail?id=90
It just so happens that in V8, the built-in sort uses an unstable quicksort for large arrays but a stable insertion sort for small ones, so the rest of your analysis is correct.
The output of Math.random also doesn't seem to be very uniform. With the original code, I'm consistently seeing Erin appear first 60% of the time, and Thomas first 30% of the time. Jeremy is left with 10%.
Even after changing the code to multiply by 99 instead of 100, the results don't change very much at all.
The random return used in the comparison passed into an Array.sort() function would depend on the sort algorithm used by the JavaScript engine, since the comparisons being returned aren't "honest". Is it a merge sort, for example? Plus, it's kinda broken because if X > Y for one permutation, it should follow that Y < X if those same values are passed back in, and in this case, they' really not.
MS took advantage of this when selecting a random browser for the browser ballot years ago.
> compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.
It doesn't really matter what Math.random() is producing when the sort algorithm is undefined.
Good luck with the company, I hope you can also beat the RNG that makes or breaks a startup :)