Talk:Fisher–Yates shuffle

message: I separated testing the index from decrementing it, since doing both at once is discouraged in many standard coding styles.  Also, this makes it easier to state what n exactly means, as an invariant.  (The old version would need 'n is the maximum pertinent index', but then the initialization statement doesn't gibe with that.)  It might be more natural to move the --n to the end of the loop body (and index n-1).  I suspect a for-loop is actually more appropriate (esp. if the target reader is expected to recognize a pre/post decrement).
Should the variable 'n' be replaced with something more index-like, like 'i'?  In particular, there is confusion between the algorithm's n (which is 0-based), and the n in the pseudocode's An (which is 1-based).
Finally, I like the discussion at the end about drawbacks of pseudo-random number generators, but that's orthogonal to the current page; should this page just link to that?  (Like MaxEnt below, I kinda prefer expository treatments over encyclopedic ones in many cases.)
not-just-yeti (talk) 17:29, 14 March 2008 (UTC)
replies: text: I agree with you regarding the indices. I changed 'n' to 'i', 'k' to 'j' and 'N' to 'n', according to common convention. I hope I didn't introduce any errors. Adrianwn (talk) 05:45, 30 April 2010 (UTC)
thread_title:  code style 

message: "Below is the same algorithm in C#".  The program below that statement is obviously not the same algorithm because all of the variables have been renamed in a contradictory manner.  "n" is now "i", "k" is now "n".  How on Earth is this supposed to make sense?  Miqrogroove (talk) 22:41, 18 January 2008 (UTC)
replies: text: I cleaned up the C# code to use the same variable names, but then decided to remove it entirely since the result was nearly identical to the Java version.  Having multiple example implementations might not be a bad idea as such, but there's little point in providing minor variations for a bunch of different C-derived languages.  Let's at least have something with different-looking syntax, like Python for example.  —Ilmari Karonen (talk) 05:09, 20 January 2008 (UTC)
thread_title:  Example Programs are Confused 

message: "Also, of course, no pseudorandom number generator can produce more distinct sequences than there are distinct seed values it may be initialized with. Thus, it doesn't matter much if a generator has 1024 bits of internal state if it is only ever initialized with a 32-bit seed."
This is not necessarily true.  If we switch to a different algorithm, such as the reservoir model (cite: Knuth vol 2 section 3.4.2 algorithm R), we only need our pseudorandom number generator to produce numbers [0 N) to produce all N! sequences.  —Preceding unsigned comment added by 142.104.68.102 (talk) 23:51, 19 March 2008 (UTC)
replies: text: Interesting, I didn't know that. But maybe what the orignal author wanted to say was, that implementations probably do something like one seeding - one shuffle. Then the program terminates and the long period of the PRNG goes to a waste. I understand that is why under Unix we should use the system provided random (but I don't really know much about that). If we use a PRNG library in our program (e.g. a Mersenne Twister is provided for Free Pascal under Windows) we probably should better save the internal state of the PRNG (and reload+continue from there on the next run) instead of seeding every time we start our program. I hope that wasn't too off-topic. Reading about the potential implemenation problems here was very helpful for me; I might have fallen into one of those traps. --Stevemiller (talk) 04:09, 27 March 2008 (UTC)
thread_title:  Inaccuracy 

message: "However, care must be taken to ensure that the assigned random numbers are never duplicated, since sorting algorithms in general won't order elements randomly in case of a tie."
Isn't the whole point of the assign+sort algorithm that duplicates don't matter since which pair of numbers is duplicated depends on the distance between the same random number being produced - which is of course equally random ?
The order of the duplicates would be implementation specific, but even if you know that a particular platform always kept duplicates unswapped - you wouldn't know which pair are duplicates so there is no loss of randomness.
:I think it does matter -- consider where you only have two elements, and a tie occurs 2% of the time.  Then the first element stays first 51% of the time.  Similarly, if you have three elements and occasional ties, the first element has a (slightly) higher-than-1/3 chance of staying first. not-just-yeti (talk) 21:33, 6 October 2008 (UTC)
thread_title:  comparison with other algorithms 

message: Article section "Modulo bias" begins : "A related problem occurs with implementations that first generate a random floating-point number ...". It may be worth considering possible consequences of the following :-
Looking at some Random [0..1) , using IEEE Double, in browsers and elsewhere, I see some cases where the PRNG is 32-bit and converted to Doubles which are multiples of 2^-32 (poor, but OK), and some with 53 bits of PRNG  making Double multiples of 2^-53 (no problem, if done correctly) - and I hear of one, in Mac iCab, which apparently takes a 64-bit PRNG, divides by 2^64, and returns the nearest Double.  In that final case, the absolute "fineness" of the Doubles varies with magnitude.  That could have some effect on results.
ASIDE : I see mo links to Wikipedia on Random [0..1) as opposed to PRNG generating integers.  Many Wiki pages have a "see also" section near the end.  But as yet I see no page dealing with Random [0..1) (which would make a link even more useful if such exists).
82.163.24.100 (talk) 15:23, 21 August 2008 (UTC)
thread_title:  Float resolution evenness 

message: 131.15.48.58 recently [ added the following comment] to the article page:
I've removed the comment from the article and placed it here where it belongs.  The answer, incidentally, is yes: in the Limited PRNG state space section, I did assume that the array being shuffled and as well as the internal state of the PRNG would be reset between runs.  If you store the shuffled array and use it as the initial state for the next shuffle, you'll do much better: in fact, you've essentially made the array part of the PRNG state, increasing the effective period by a factor of up to N! (and probably at least a significant fraction of that) where N is the length of the array.
(This is precisely why the often half-hearted shuffling of real card decks manages to produce such a good semblance of randomness: depending on the game, the deck usually retains significant randomness even after a round of play, and just needs a bit of mixing to appear mostly random again.  Effectively, the deck itself acts as a roughly 226-bit PRNG (or more accurately, since some true randomness is being injected, an entropy pool), with the shuffle plus the game forming the transition function.  This is also why a new, sorted deck needs extra shuffling before use.  The Solitaire cipher is based on a similar idea.)  —Ilmari Karonen (talk) 23:22, 11 September 2008 (UTC)
thread_title:  PRNG state (moved from article page) 

message: The Java version has the comment:
int k = rng.nextInt(n);  // 0 <= k <= n.
But actually Java's nextInt(n) method returns a k such that 0 <= k < n. And this fact is vitally important! If k == n, then we would index outside of the array. This caught me when translating the Java code into another language, and I used the comment at face value.  —Preceding unsigned comment added by 79.78.227.249 (talk) 12:03, 3 October 2009 (UTC)
replies: text: Note the most recent edit to the code.  Did that leave the code correct but the comment broken? -- ToET 13:15, 3 October 2009 (UTC)

text: I've updated the comment to match the code change.-- ToET 13:23, 3 October 2009 (UTC)
thread_title:  Java example code appears to be wrong 

message: The shuffle can't be O(n), because it requires us to generate random numbers in the ranges [1, 1], [1, 2], ..., [1, n]. Since generating a random number in the range [1, x] requires log2(x) random bits, the total number of random bits needed is log2(1) + log2(2) + log2(3) + ... + log2(n) = log2(n!) = O(n log n). A PRNG or HRNG can't possibly run in less than constant time per bit, so the shuffle as a whole can't be faster than O(n log n). NB: Since a list of length n has n! permutations and it takes log2(n!) random bits to choose among them, similar reasoning shows that no unbiased shuffle can be faster than O(n log n). NeonMerlin 22:46, 17 December 2009 (UTC)
replies: text: When you say "we typically agree that fundamental numeric operations take constant time", do you mean that in the limiting case memory words are infinitely long and the supply of input entropy (if we're using an HRNG) is infinite? NeonMerlin 08:26, 31 December 2009 (UTC)
thread_title:  Not O(n) 

message: Since no source is cited for the (various language) implementations, then surely these constitute "Original Research" and should be struck out.
(Note : I don't disagree with this sort of thing being posted ; but I've been slapped down often enough for posting "original research" that I'd like to hear how/why this shouldn't suffer the same fate.)  —Preceding unsigned comment added by A Karley (talk • contribs) 13:41, 1 March 2010 (UTC)
thread_title:  Original Research 

message: Why are there examples in so many different languages?  It gets in the way of the point of the article (which is shuffling, not a comparison of different languages).  Also, as demonstrated in the other discussion topics for this page, it leads to several incorrect and/or contradictory examples.  There should be one example and it should be an an ideal implementation of this algorithm in pseudocode.  Any, competent programmer can then implement it in their language of choice for their use.
Adam Butt (talk) 19:26, 1 March 2010 (UTC)
replies: text: Ditto, you should feel free to get rid of extraneous examples. I've cleared out many. — sligocki (talk) 04:54, 2 March 2010 (UTC)
replies: text:  I agree that all the explicit code serves little purpose. Note that pseudocode is already there, for the main cases. However, some stuff in the article refers to previous (or removed) code examples, so care should be taken to leave/bring the text in a consistent state. Marc van Leeuwen (talk) 13:13, 2 March 2010 (UTC)
thread_title:  Too many examples. 

message: The Python code, as given, produces an index error in "items". To fix, in the expression "range(2, len(items) + 1)" on line 4, remove "+ 1" to get: "range(2, len(items))". 
The function range(start, end[, step]) returns a list containing the integers from <start> to the one preceding <end>, with the option of controlling step size and direction with the third argument. Indices in python start with 0, therefore the last element has an index of <length-1>. Therefore, "range(2, <length+1>)" will make the program try to access the element behind the last, which does not exist.
Also, the description of the "modern algorithm" calls for randomization to start with index 1, not 2, for 0-based indices (where an index of 1 means the _second_ element), which means the 2 should get replaced by a 1.
All of this in mind, I suggest to change the complete line to read (without the quotes):
"for n in range(len(items)-1, 0, -1):"
This will count down from the last element to the second (inclusive). Getting the reversed list right away seems more efficient than having to iterate a second time just to reverse.
Til
85.178.23.84 (talk) 19:20, 23 April 2010 (UTC)
replies: text: Yeah, sorry for confusing the mistake. I have reverted. Probably better not to try and make this more pythonic, it just needs to be an algorithm which is clear the way it is.  Cheers, — sligocki (talk) 04:19, 24 April 2010 (UTC)
replies: text:  Agreed, good point about the need for clarity here. The algorithm's much less obscure without the python specifics. Til 85.178.23.84 (talk) 09:05, 24 April 2010 (UTC)
thread_title:  Python example seems wrong 

message: I don't want to change anything yet since it might be me who am stupid. But I'm fairly sure this is wrong in at least the modern algorithm:
j ← random integer with 0 ≤ j ≤ i
This should be non-inclusive of i, as in j ← random integer with 0 ≤ j < i
There are probably errors in the other examples as well but I haven't verified them.
How do I know this? I tried it. It doesn't work if i is inclusive, it does seem to work if it's not inclusive.  — Preceding unsigned comment added by 213.103.201.140 (talk) 18:48, 29 March 2013 (UTC)
replies: text: I don't see a problem. In first alg, the outer loop has i march down from n−1, so an inclusive random is not out of range for the array. Glrx (talk) 18:23, 30 March 2013 (UTC)
thread_title:  Illegal offset by one in examples 

message: This is a great article, overall but I have a little problem. Maybe it's I who is dumb, but the difference between those are not clear. It just says you can accidently implement Sattolo instead of Fisher-Yates, but it doesn't explain for people who aren't familiar with math theory, what is the difference between a "permuation" and a "cycle", from a computer science (not math) perspective.85.1.241.60 (talk) 23:21, 20 January 2014 (UTC)
thread_title:  Difference between "permuation" (Fisher-Yates) and "cycle" (Sattolo) 

message: I'm tempted to adjust the Inside-Out shuffle to the following as the loop's first cycle is pointless. Any thoughts? 203.109.198.155 (talk) 21:43, 19 May 2014 (UTC)
thread_title:  Inside-Out Adjustment 

message: Pseudorandom number generator
Start with such a thing. Scale output to number of tunes. Use series calculated as an index for numbers to exchange in an array of counting to avoid duplication. The other index is another count. Get a list of tunes in track or alphabetical order (which might be the same). Number tunes according to your random series. Radix Sort tunes by numbers.
If you run WinAmp, press misc/sort/randomize list, then play the tunes *in order* ("123" is dark), then you can see some of this.
70.74.164.9 (talk) 15:41, 5 February 2015 (UTC)
thread_title:  Plain English Description? 

message: for i from 0 to n − 1 do
        j ← random integer with i ≤ j < n
        exchange a[j] and a[i]
in this code last iteration will always do nothing because j will be equal to i, therefore loop might as well be to n - 2 Norill (talk) 16:53, 7 April 2015 (UTC)
thread_title:  last step 

message: Are there other ways modulo bias can be avoided/minimized?  Should there be a separate article (or at least a redirect) specifically for it?  I just ran into the term while looking for information about the ObjC/Swift PRNG function arc4random_uniform(), which is supposed to avoid it. (So I don't know enough about it to WP:BOLD :) Jimw338 (talk) 07:10, 4 July 2015 (UTC)
replies: text: Rejection sampling. Glrx (talk) 17:56, 7 July 2015 (UTC)
thread_title:  Separate (Additional) article specifically for Modulo Bias? 

message: This variation recently occurred to me:
 -- Randomly shuffle array a[0...n-1]
 for i from 1 to n-1 do
     r ← random value, where 0 ≤ r < 1
     if r < 0.5 then
         exchange a[0] and a[i]
The loop shuffles the array by randomly deciding whether or not to swap the first card with the 2nd card, then the 3rd card, and so on until the last card is reached; each swap has a 50% chance of occurring. If this is indeed a valid working algorithm, then I am certainly not the first one to think of it, so it undoubtedly has a formal name. (I am not entirely certain, however, if it is capable of producing all n! permutations of the elements of a.) If it is, then the question is, is this algorithm similar enough to the F-Y algorithm to be considered a variation of it, and thus be worthy of mention in the article? — Loadmaster (talk) 18:08, 29 December 2015 (UTC)
replies: text: WP is not a place for your WP:OR. You need to have reliable sources for algorithms. I doubt you'll find a reliable source for the above nonsense. The last element, a[n−1] can only end up in two places rather than n places. You should also consider . And that doesn't even start to address bias. a[0] is exponentially more likely to make it to position  than position . Glrx (talk) 18:26, 29 December 2015 (UTC)
replies: text: Well, thank you for the positive critique. Just thought I'd ask, since I was curious about it. I did not intend it to be OR, but rather thought that it might be another existing variant of F-Y. But as you show, it is not. — Loadmaster (talk) 19:13, 29 December 2015 (UTC)
thread_title:  Another (equivalent?) algorithm 

message: I can't see much relationship between them.  If inside-out is Fisher-Yates, then what algorithm to choose uniformly from the $n!$ options is not Fisher-Yates? --73.93.124.14 (talk) 07:19, 4 August 2016 (UTC)
thread_title:  Is "inside-out" really Fisher-Yates? 

message: The description of the "modern method" says nothing about inserting to the output list at the head. The previous example appends the newly selected item to the end to the list, which seems more clear.
Is there a specific reason to put the newly selected number at the beginning of the output list?
<<
For our first roll, we roll a random number from 1 to 8: this time it is 6, so we swap the 6th and 8th numbers in the list:
Range	Roll	Scratch Result	
1-8  	6   	1 2 3 4 5 8 7 	6
The next random number we roll from 1 to 7, and turns out to be 2. Thus, we swap the 2nd and 7th numbers and move on:
Range	Roll	Scratch Result	
1-7  	2   	1 7 3 4 5 8   	2 6
This should be 
Range	Roll	Scratch Result	
1-7  	2   	1 7 3 4 5 8   	6 2
to match the prior example.
Mjshulman (talk) 23:05, 24 November 2017 (UTC)
thread_title:  "Example" section: Modern Method builds output in reverse order 

message: The comparison section states that methods like merge sorts are not uniform, without any reference. It then states that coin flipping with a bounded number of times cannot produce uniform results, but then providing a calculation for the situation with a fixed number of coin-flips. Since the merge sort does not need a fixed number of coin-flips, the comparison does not apply and the statements are misleading.
I suggest that those un-referenced and IMO misleading statements are removed.
90.145.31.194 (talk) 16:28, 8 February 2019 (UTC)
replies: text: The argument is correct, and applies whenever the number of coin flips is bounded, not just when it is fixed. (A bounded coin flip algorithm can be thought of as one that flips a fixed number of coins, the number given by the bound, but then might not look at some of them, so the two models are not really different.) In merge sort with coin flips replacing the comparisons, the number of flips is indeed bounded. So you can only get probabilities per permutation that are dyadic rational numbers (with powers of two as denominators). But the correct probabilities have other denominators, so this algorithm does not generate the correct probabilities. —David Eppstein (talk) 17:11, 8 February 2019 (UTC)
replies: text: Thanks for the clarification. I still think more references are required, since the only reference now is the specific case of the Microsoft Browser Selection with 5 options. 90.145.31.194 (talk) 12:56, 12 February 2019 (UTC)
thread_title:  Comparison: misleading statements 

message: [Edit: OK I added a short section with code example of what not to do. Hopefully it will help prevent readers from using a naive method.]  — Preceding unsigned comment added by Ericjster (talk • contribs) 07:13, 9 December 2019 (UTC)
thread_title:  Need to compare with naive/simple method 

message: Sorry but what does "counting from the low end" mean? I googled this phrase and this article is the only time this phrase is used, on the entire internet.  — Preceding unsigned comment added by 82.46.42.169 (talk) 10:02, 16 July 2020 (UTC)
thread_title:  Low end? 

message: The “inside-out” algorithm always begins by copying the first element of the source to the first element of the destination. It then relies on random chance to swap that out later. This seems to be biased in favour of keeping it there. The probabilities for each element also don’t reek like an even 50% either. Some proofs would be welcome.
mirabilos (talk) 20:15, 26 September 2020 (UTC)
thread_title:  “inside-out” seems to be biased, no truly random shuffle 

message: On the one hand, shuffling 'sycophant' into 'actsphony' is amusing, but given that it's clearly been chosen rather than being random, is it the best example that there could be? Lovingboth (talk) 10:16, 20 October 2021 (UTC)
thread_title:  First example graphic