@@ -2229,6 +2229,30 @@ def test_permutations_sizeof(self):
22292229... # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
22302230... return next(filter(pred, iterable), default)
22312231
2232+ >>> def nth_combination(iterable, r, index):
2233+ ... 'Equivalent to list(combinations(iterable, r))[index]'
2234+ ... pool = tuple(iterable)
2235+ ... n = len(pool)
2236+ ... if r < 0 or r > n:
2237+ ... raise ValueError
2238+ ... c = 1
2239+ ... k = min(r, n-r)
2240+ ... for i in range(1, k+1):
2241+ ... c = c * (n - k + i) // i
2242+ ... if index < 0:
2243+ ... index += c
2244+ ... if index < 0 or index >= c:
2245+ ... raise IndexError
2246+ ... result = []
2247+ ... while r:
2248+ ... c, n, r = c*r//n, n-1, r-1
2249+ ... while index >= c:
2250+ ... index -= c
2251+ ... c, n = c*(n-r)//n, n-1
2252+ ... result.append(pool[-1-n])
2253+ ... return tuple(result)
2254+
2255+
22322256This is not part of the examples but it tests to make sure the definitions
22332257perform as purported.
22342258
@@ -2312,6 +2336,15 @@ def test_permutations_sizeof(self):
23122336>>> first_true('ABC0DEF1', '9', str.isdigit)
23132337'0'
23142338
2339+ >>> population = 'ABCDEFGH'
2340+ >>> for r in range(len(population) + 1):
2341+ ... seq = list(combinations(population, r))
2342+ ... for i in range(len(seq)):
2343+ ... assert nth_combination(population, r, i) == seq[i]
2344+ ... for i in range(-len(seq), 0):
2345+ ... assert nth_combination(population, r, i) == seq[i]
2346+
2347+
23152348"""
23162349
23172350__test__ = {'libreftest' : libreftest }
0 commit comments