P is for Practical  
PerlMonks 
Re^4: Random Derangement Of An Arrayby dcturner (Initiate) 
on Dec 08, 2008 at 19:11 UTC ( #729013=note: 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 Section
Seekers of Perl Wisdom

