I was trying to create a small script that will take the list of elements and create all the possible permutations of its contents, while all those permutations may have repetitions and have to be of size n and contain all the original values. I tried to use the itertools
library but they don't have anything of use. Is there something simple I can do to achieve that?
Here is an example for the list [0,1,2]
and n=3
:
[0,1,2]
[0,2,1]
[1,0,2]
[2,0,1]
[1,2,0]
[2,1,0]
For n=4
, something like [0,1,1,2]
will also be allowed in the output.
The behavior you described can be implemented with the following function:
def perms_with_duplicates(lst: list, n: int) -> Iterator:
"""
Generate permutations of ``lst`` with length ``n``.
If ``n`` is greater than the length of ``lst``, then the
resulting permutations will include duplicate elements
from ``lst``. All of the original elements of ``lst``
are guaranteed to appear in each output permutation.
"""
# Number of duplicate entries that the permutations can include.
num_dupl = max(n - len(lst) + 1, 1)
return itertools.permutations(lst * num_dupl, n)
Alternatively, if you need this to work over any sequence, instead of just for lists, you could use
def perms_with_duplicates(seq: Sequence, n: int) -> Iterator:
"""
Generate permutations of ``seq`` with length ``n``.
If ``n`` is greater than the length of `seq`, then the
resulting permutations will include duplicate elements
from ``seq``. All of the original elements of ``seq``
are guaranteed to appear in each output permutation.
"""
# Number of duplicate entries that the permutations can include.
num_dupl = max(n - len(seq) + 1, 1)
it_dupl = itertools.chain.from_iterable(
itertools.repeat(seq, num_dupl)
)
return itertools.permutations(it_dupl, n)
Both functions behave as follows. Note that for n
less than or equal to the length of the input sequence, the functions behave exactly like itertools.permutations
.
>>> l = [0, 1, 2]
>>> list(perms_with_duplicates(l, 3))
[(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
>>> len(list(perms_with_duplicates(l, 4)))
360
>>> list(perms_with_duplicates(l, 4))
[(0, 1, 2, 0),
(0, 1, 2, 1),
(0, 1, 2, 2),
(0, 1, 0, 2),
(0, 1, 0, 1),
...
(1, 2, 1, 0),
(1, 2, 1, 0),
(1, 2, 1, 2),
(1, 2, 0, 0),
(1, 2, 0, 1),
...
(2, 1, 0, 2)]