@@ -838,10 +838,10 @@ and :term:`generators <generator>` which incur interpreter overhead.
838838
839839.. testcode ::
840840
841- from collections import deque
841+ from collections import Counter, deque
842842 from contextlib import suppress
843843 from functools import reduce
844- from math import sumprod, isqrt
844+ from math import comb, prod, sumprod, isqrt
845845 from operator import itemgetter, getitem, mul, neg
846846
847847 def take(n, iterable):
@@ -1127,6 +1127,12 @@ The following recipes have a more mathematical flavor:
11271127 n -= n // prime
11281128 return n
11291129
1130+ def multinomial(*counts):
1131+ "Number of distinct arrangements of a multiset."
1132+ # Counter('abracadabra').values() -> 5 2 1 1 2
1133+ # multinomial(5, 2, 1, 1, 2) → 83160
1134+ return prod(map(comb, accumulate(counts), counts))
1135+
11301136
11311137.. doctest ::
11321138 :hide:
@@ -1730,6 +1736,12 @@ The following recipes have a more mathematical flavor:
17301736 >>> ' ' .join(it)
17311737 'DEF1'
17321738
1739+ >>> multinomial(5 , 2 , 1 , 1 , 2 )
1740+ 83160
1741+ >>> word = ' coffee'
1742+ >>> multinomial(* Counter(word).values()) == len (set (permutations(word)))
1743+ True
1744+
17331745
17341746.. testcode ::
17351747 :hide:
0 commit comments