mirror of
https://github.com/python/cpython.git
synced 2026-01-18 05:10:02 +00:00
Update random combinatoric recipes and add tests (gh-143762)
This commit is contained in:
parent
298d5440eb
commit
a6bc60da02
1 changed files with 83 additions and 8 deletions
|
|
@ -634,11 +634,12 @@ from the combinatoric iterators in the :mod:`itertools` module
|
|||
or the :pypi:`more-itertools` project:
|
||||
|
||||
.. testcode::
|
||||
|
||||
import random
|
||||
|
||||
def random_product(*args, repeat=1):
|
||||
"Random selection from itertools.product(*args, **kwds)"
|
||||
pools = [tuple(pool) for pool in args] * repeat
|
||||
def random_product(*iterables, repeat=1):
|
||||
"Random selection from itertools.product(*iterables, repeat=repeat)"
|
||||
pools = tuple(map(tuple, iterables)) * repeat
|
||||
return tuple(map(random.choice, pools))
|
||||
|
||||
def random_permutation(iterable, r=None):
|
||||
|
|
@ -663,15 +664,89 @@ or the :pypi:`more-itertools` project:
|
|||
return tuple(pool[i] for i in indices)
|
||||
|
||||
def random_derangement(iterable):
|
||||
"Choose a permutation where no element is in its original position."
|
||||
"Choose a permutation where no element stays in its original position."
|
||||
seq = tuple(iterable)
|
||||
if len(seq) < 2:
|
||||
raise ValueError('derangements require at least two values')
|
||||
perm = list(seq)
|
||||
if not seq:
|
||||
return ()
|
||||
raise IndexError('No derangments to choose from')
|
||||
perm = list(range(len(seq)))
|
||||
start = tuple(perm)
|
||||
while True:
|
||||
random.shuffle(perm)
|
||||
if all(p != q for p, q in zip(seq, perm)):
|
||||
return tuple(perm)
|
||||
if all(p != q for p, q in zip(start, perm)):
|
||||
return tuple([seq[i] for i in perm])
|
||||
|
||||
.. doctest::
|
||||
:hide:
|
||||
|
||||
>>> import random
|
||||
|
||||
|
||||
>>> random.seed(8675309)
|
||||
>>> random_product('ABCDEFG', repeat=5)
|
||||
('D', 'B', 'E', 'F', 'E')
|
||||
|
||||
|
||||
>>> random.seed(8675309)
|
||||
>>> random_permutation('ABCDEFG')
|
||||
('D', 'B', 'E', 'C', 'G', 'A', 'F')
|
||||
>>> random_permutation('ABCDEFG', 5)
|
||||
('A', 'G', 'D', 'C', 'B')
|
||||
|
||||
|
||||
>>> random.seed(8675309)
|
||||
>>> random_combination('ABCDEFG', 7)
|
||||
('A', 'B', 'C', 'D', 'E', 'F', 'G')
|
||||
>>> random_combination('ABCDEFG', 6)
|
||||
('A', 'B', 'C', 'D', 'F', 'G')
|
||||
>>> random_combination('ABCDEFG', 5)
|
||||
('A', 'B', 'C', 'E', 'F')
|
||||
>>> random_combination('ABCDEFG', 4)
|
||||
('B', 'C', 'D', 'G')
|
||||
>>> random_combination('ABCDEFG', 3)
|
||||
('B', 'E', 'G')
|
||||
>>> random_combination('ABCDEFG', 2)
|
||||
('E', 'G')
|
||||
>>> random_combination('ABCDEFG', 1)
|
||||
('C',)
|
||||
>>> random_combination('ABCDEFG', 0)
|
||||
()
|
||||
|
||||
|
||||
>>> random.seed(8675309)
|
||||
>>> random_combination_with_replacement('ABCDEFG', 7)
|
||||
('B', 'C', 'D', 'E', 'E', 'E', 'G')
|
||||
>>> random_combination_with_replacement('ABCDEFG', 3)
|
||||
('A', 'B', 'E')
|
||||
>>> random_combination_with_replacement('ABCDEFG', 2)
|
||||
('A', 'G')
|
||||
>>> random_combination_with_replacement('ABCDEFG', 1)
|
||||
('E',)
|
||||
>>> random_combination_with_replacement('ABCDEFG', 0)
|
||||
()
|
||||
|
||||
|
||||
>>> random.seed(8675309)
|
||||
>>> random_derangement('')
|
||||
()
|
||||
>>> random_derangement('A')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: No derangments to choose from
|
||||
>>> random_derangement('AB')
|
||||
('B', 'A')
|
||||
>>> random_derangement('ABC')
|
||||
('C', 'A', 'B')
|
||||
>>> random_derangement('ABCD')
|
||||
('B', 'A', 'D', 'C')
|
||||
>>> random_derangement('ABCDE')
|
||||
('B', 'C', 'A', 'E', 'D')
|
||||
>>> # Identical inputs treated as distinct
|
||||
>>> identical = 20
|
||||
>>> random_derangement((10, identical, 30, identical))
|
||||
(20, 30, 10, 20)
|
||||
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue