P is for Practical  
PerlMonks 
Comment on 
( #3333=superdoc: print w/ replies, xml )  Need Help?? 
Here is a recent article describing a simpler algorithm for sampling derangements... Ah yes, that's nice. I think there is a slight buglet in the given code: $j = 1 + int rand($i2) while $mark[$j];should read $j = 1 + int rand($i1) while $mark[$j];should it not? Also it could hit an overflow bug for $n > 12, because d_n gets quite large quite quickly. Even with 64bit ints you overflow for $n > 20. The same approximation works for your method as for mine: for $n > 12 the value (n1)d_{n2} / d_n is very close to 1/n. The iterative version of the recursive program that I wrote above is as follows. It's a bit convoluted because the recursion d_n = (n1) (d_{n1} + d_{n2}) is secondorder, so you have to work a bit harder than for a firstorder recursion. It's also inplace and requires only a constant amount of auxiliary storage. Plus it certainly terminates, whereas the rejection method merely almost certainly terminates :) On the minus side, it is a bit quadratic (although with low probability). Sidebyside, they run pretty similarly it seems.
In reply to Re^4: Random Derangement Of An Array
by dcturner

