You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For an array of $n$ elements, there are exactly $n!$ permutations (i.e. possible shuffles).
Every comparison during a shuffle is a choice between two sets of permutations. For a random comparator, there is a $\frac{1}{2}$ chance of choosing each set.
For each permutation $p$, the chance of ending up with permutation $p$ is a fraction with denominator $2^k$ (for some $k$), because it is a sum of such fractions (e.g. $\frac{1}{8} + \frac{1}{16} = \frac{3}{16}$).
For $n = 3$, there are six equally-likely permutations. The chance of each permutation, then, is $\frac{1}{6}$. This can't be expressed as a fraction with a power of 2 as its denominator.
Therefore, the coin flip sort will never result in a fair distribution of shuffles.
Example
A short visualisation of the problem would be this:
Divide a cake among six people1 but you can only do so by cutting a piece exactly into two equal halves2. Either you'll end up with two extra pieces (eight equal pieces), or you'll end up with four smaller pieces and two bigger pieces3.
Other issues
The sort is not well-defined, as it generates a random number for each individual comparison. You could define a sort as completed when for every comparison between two adjacent elements, they are always correctly ordered. Mathematically this sort should never return and run forever. This proves that the actual result is heavily implementation dependent.
Proposed solution
Change it to a Schwartzian transform shuffle, I think the result will be just as good as Fisher-Yates used by the BMM app, but I think the algorithm is much easier to understand.
['A','B','C']// Wrap each entry and add a random sort number,// assume that the chance that two entries get exactly the same value is negligible.map((x)=>({original: x,sort: Math.random()}))// Sort by the random numbers.sort((a,b)=>(a.sort-b.sort))// Remove the random numbers and restore the original data.map(({ original })=>original);
Footnotes
Representing the six possible permutations of an array with three elements. ↩
Representing the 50% chance / coin flip implemented as random() - 0.5↩
This is what happens in practice, some permutations have higher chance of appearing than others. ↩
The text was updated successfully, but these errors were encountered:
Ghostbird
changed the title
Shuffle algorithm is not a shuffle algorithm
Shuffle algorithm is not a proper shuffle algorithm
Sep 20, 2023
This is not a random shuffle algorithm:
bmm-web/plugins/mediaPlayer/Queue.ts
Line 47 in 284ec84
Proof
Example
A short visualisation of the problem would be this:
Divide a cake among six people1 but you can only do so by cutting a piece exactly into two equal halves2. Either you'll end up with two extra pieces (eight equal pieces), or you'll end up with four smaller pieces and two bigger pieces3.
Other issues
The sort is not well-defined, as it generates a random number for each individual comparison. You could define a sort as completed when for every comparison between two adjacent elements, they are always correctly ordered. Mathematically this sort should never return and run forever. This proves that the actual result is heavily implementation dependent.
Proposed solution
Change it to a Schwartzian transform shuffle, I think the result will be just as good as Fisher-Yates used by the BMM app, but I think the algorithm is much easier to understand.
Footnotes
Representing the six possible permutations of an array with three elements. ↩
Representing the 50% chance / coin flip implemented as
random() - 0.5
↩This is what happens in practice, some permutations have higher chance of appearing than others. ↩
The text was updated successfully, but these errors were encountered: