Skip to content

Commit b9a730d

Browse files
rhettingerlkollar
authored andcommitted
Add random_derangement recipe pythongh-138377
1 parent aa071ed commit b9a730d

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

Doc/library/random.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,8 @@ Recipes
630630
-------
631631

632632
These recipes show how to efficiently make random selections
633-
from the combinatoric iterators in the :mod:`itertools` module:
633+
from the combinatoric iterators in the :mod:`itertools` module
634+
or the :pypi:`more-itertools` project:
634635

635636
.. testcode::
636637
import random
@@ -661,6 +662,17 @@ from the combinatoric iterators in the :mod:`itertools` module:
661662
indices = sorted(random.choices(range(n), k=r))
662663
return tuple(pool[i] for i in indices)
663664

665+
def random_derangement(iterable):
666+
"Choose a permutation where no element is in its original position."
667+
seq = tuple(iterable)
668+
if len(seq) < 2:
669+
raise ValueError('derangments require at least two values')
670+
perm = list(seq)
671+
while True:
672+
random.shuffle(perm)
673+
if all(p != q for p, q in zip(seq, perm)):
674+
return tuple(perm)
675+
664676
The default :func:`.random` returns multiples of 2⁻⁵³ in the range
665677
*0.0 ≤ x < 1.0*. All such numbers are evenly spaced and are exactly
666678
representable as Python floats. However, many other representable

0 commit comments

Comments
 (0)