You want to generate all permutations of the np.repeat([1,2,3], 300)
multiset. There is an algorithm that allows to generate the next permutation in O(1)
. Here's a simple algorithm that uses C++ std::next_permutation()
function and prints permutations in a lexicographical order:
#!/usr/bin/env python
"""Print all multiset permutations."""
import pyximport; pyximport.install() # $ pip install cython
from next_permutation import next_permutation
n = 3
multiset = bytearray('a'*n + 'b'*n + 'c'*n)
print(multiset)
while next_permutation(multiset):
print(multiset)
Where next_permutation
module is a C extension module for Python defined in Cython:
# cython: boundscheck=False
#file: next_permutation.pyx
cimport cpython.array # support array.array() on Python 2
from libcpp cimport bool
ctypedef unsigned char dtype_t
ctypedef dtype_t* Iter
cdef extern from "<algorithm>" namespace "std":
bool cpp_next_permutation "std::next_permutation" (Iter first, Iter last)
def next_permutation(dtype_t[:] a not None):
return cpp_next_permutation(&a[0], &a[0] + a.shape[0])
To build it, specify that the language is C++:
#file: next_permutation.pyxbld
from distutils.extension import Extension
def make_ext(modname, pyxfilename):
return Extension(name=modname,
sources=[pyxfilename],
language="c++")
Output
aaabbbccc
aaabbcbcc
aaabbccbc
aaabbcccb
aaabcbbcc
aaabcbcbc
aaabcbccb
aaabccbbc
aaabccbcb
aaabcccbb
aaacbbbcc
aaacbbcbc
aaacbbccb
aaacbcbbc
aaacbcbcb
aaacbccbb
..snip..
cccaabbba
cccabaabb
cccababab
cccababba
cccabbaab
cccabbaba
cccabbbaa
cccbaaabb
cccbaabab
cccbaabba
cccbabaab
cccbababa
cccbabbaa
cccbbaaab
cccbbaaba
cccbbabaa
cccbbbaaa
next_permutation()
function accept anything that supports buffer interface e.g., it support numpy arrays:
import numpy as np
multiset = np.repeat(np.array([1,2,3], dtype=np.uint8), 3)