From: Raymond Hettinger Date: Thu, 4 Sep 2025 15:50:29 +0000 (-0500) Subject: Add random_derangement recipe gh-138377 X-Git-Tag: v3.15.0a1~491 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f9a40c386d4d07dab1c15c6618807306a5119818;p=thirdparty%2FPython%2Fcpython.git Add random_derangement recipe gh-138377 --- diff --git a/Doc/library/random.rst b/Doc/library/random.rst index b1120b3a4d8e..e9cebf46d57b 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -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