.. testcode::
- from collections import deque
+ from collections import Counter, deque
from contextlib import suppress
from functools import reduce
- from math import sumprod, isqrt
+ from math import comb, prod, sumprod, isqrt
from operator import itemgetter, getitem, mul, neg
def take(n, iterable):
n -= n // prime
return n
+ def multinomial(*counts):
+ "Number of distinct arrangements of a multiset."
+ # Counter('abracadabra').values() -> 5 2 1 1 2
+ # multinomial(5, 2, 1, 1, 2) → 83160
+ return prod(map(comb, accumulate(counts), counts))
+
.. doctest::
:hide:
>>> ''.join(it)
'DEF1'
+ >>> multinomial(5, 2, 1, 1, 2)
+ 83160
+ >>> word = 'coffee'
+ >>> multinomial(*Counter(word).values()) == len(set(permutations(word)))
+ True
+
.. testcode::
:hide: