]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Add random_derangement recipe gh-138377
authorRaymond Hettinger <rhettinger@users.noreply.github.com>
Thu, 4 Sep 2025 15:50:29 +0000 (10:50 -0500)
committerGitHub <noreply@github.com>
Thu, 4 Sep 2025 15:50:29 +0000 (10:50 -0500)
Doc/library/random.rst

index b1120b3a4d8eb4e8bc88dd99ad29d236fc47523e..e9cebf46d57b01ddffaee81cd014d6fb4eecf071 100644 (file)
@@ -630,7 +630,8 @@ Recipes
 -------
 
 These recipes show how to efficiently make random selections
-from the combinatoric iterators in the :mod:`itertools` module:
+from the combinatoric iterators in the :mod:`itertools` module
+or the :pypi:`more-itertools` project:
 
 .. testcode::
    import random
@@ -661,6 +662,17 @@ from the combinatoric iterators in the :mod:`itertools` module:
        indices = sorted(random.choices(range(n), k=r))
        return tuple(pool[i] for i in indices)
 
+   def random_derangement(iterable):
+       "Choose a permutation where no element is in its original position."
+       seq = tuple(iterable)
+       if len(seq) < 2:
+           raise ValueError('derangments require at least two values')
+       perm = list(seq)
+       while True:
+           random.shuffle(perm)
+           if all(p != q for p, q in zip(seq, perm)):
+               return tuple(perm)
+
 The default :func:`.random` returns multiples of 2⁻⁵³ in the range
 *0.0 ≤ x < 1.0*.  All such numbers are evenly spaced and are exactly
 representable as Python floats.  However, many other representable