给定一组n个项目,我想生成我们可以从这个集合中选择的所有方法(替换)k次,这样订单很重要,每个元素至少使用一次。所以k> = n有任何有效的安排。如果k = n,这只是一种排列。所以k> n有点像排列的扩展,但我不知道它叫什么。
当然很容易得到 算法,虽然速度非常慢:只需迭代所有可能的选择并抛弃那些至少没有每个元素的算法。因此,为了提高效率,需要类似于迭代排列的技巧,或者将其分解为可以直接使用现有排列算法的子问题。
我尝试通过使用python执行类似下面的操作,将其分解为排列和组合问题。
import itertools
def func(inputSet,k):
n = len(inputSet)
assert(k>n)
# first, guarantee we have each element once
for p in itertools.permutations(inputSet):
# now select (k-n) locations to insert other elements
for c in itertools.combinations_with_replacement(range(n+1),k-n):
insertions = [c[i]+i for i in range(len(c))]
out = list(p)
for index in insertions:
out.insert(index,0)
# now select values to put in those locations
for vals in itertools.product(inputSet,repeat=len(insertions)):
for i in xrange(len(insertions)):
out[c[i]] = vals[i]
yield tuple(out)
但是不同的插入可以产生相同的结果,因此第一次刺入可能不会从正确的路径开始。我可以添加条件来检查这些情况并过滤掉一些结果,但是用于求解过滤的组合迭代问题的算法可能不是最有效的算法。
这个“排列扩展”是否有名称?
迭代这些安排的有效算法是什么?
答案 0 :(得分:1)
对于它所称的内容,这与排列相同,只是略有不同。考虑一组元素P,你基本上要求生成与P的(k-n)个元素联合的集合P中的所有排列,可以用itertools.combinations_with_replacement找到。
要生成实际排列,您可以使用list(set(itertools.permutations))
或more_itertools.distinct_permutations
:https://more-itertools.readthedocs.io/en/latest/api.html#more_itertools.distinct_permutations
将其纳入实际代码
>>> x = [1,2,3]
>>> k = 5
>>> results = set()
>>> for y in itertools.combinations_with_replacement(x, k - len(x)):
... for z in itertools.permutations(x + list(y)):
... results.add(z)
...
>>> results
set([(1, 1, 1, 2, 3), (1, 3, 3, 1, 2), (1, 2, 3, 3, 2), (3, 3, 2, 1, 3), (1, 3, 3, 2, 2), (1, 1, 2, 2, 3), (3, 1, 2, 3, 2), (1, 1, 3, 2, 3), (1, 3, 1, 2, 2), (1, 2, 2, 1, 3), (3, 2, 1, 2, 2), (3, 1, 2, 1, 2), (3, 2, 1, 3, 1), (3, 1, 1, 3, 2), (2, 3, 3, 2, 1), (1, 2, 1, 3, 3), (3, 1, 2, 3, 3), (2, 3, 2, 1, 1), (2, 3, 2, 2, 1), (1, 2, 2, 3, 3), (2, 1, 3, 2, 3), (2, 2, 2, 3, 1), (1, 3, 2, 2, 3), (2, 3, 3, 1, 1), (1, 2, 1, 1, 3), (3, 2, 2, 1, 1), (2, 1, 2, 2, 3), (2, 2, 1, 3, 1), (1, 3, 3, 2, 3), (2, 3, 3, 1, 3), (3, 2, 3, 2, 1), (3, 2, 3, 1, 1), (2, 1, 1, 2, 3), (3, 3, 1, 1, 2), (3, 2, 2, 2, 1), (2, 2, 3, 2, 1), (1, 3, 1, 2, 3), (2, 2, 3, 1, 2), (3, 1, 2, 1, 3), (2, 1, 1, 3, 3), (3, 3, 2, 2, 1), (1, 1, 2, 3, 1), (1, 2, 2, 3, 2), (3, 2, 1, 1, 2), (2, 1, 3, 2, 2), (1, 3, 2, 2, 2), (3, 1, 1, 1, 2), (3, 3, 2, 1, 1), (2, 3, 3, 1, 2), (3, 2, 1, 3, 2), (1, 2, 1, 3, 1), (2, 3, 1, 2, 3), (1, 2, 3, 2, 1), (3, 1, 3, 1, 2), (3, 3, 1, 2, 2), (1, 2, 3, 1, 1), (2, 2, 1, 1, 3), (2, 1, 1, 3, 2), (1, 1, 2, 3, 2), (3, 2, 1, 1, 3), (2, 1, 3, 2, 1), (2, 1, 1, 3, 1), (1, 3, 2, 2, 1), (1, 3, 2, 1, 1), (3, 2, 2, 1, 3), (2, 2, 3, 3, 1), (3, 1, 1, 2, 1), (2, 2, 1, 3, 3), (1, 3, 3, 2, 1), (3, 2, 3, 1, 2), (3, 1, 2, 3, 1), (2, 2, 2, 1, 3), (1, 1, 3, 1, 2), (1, 1, 2, 1, 3), (2, 1, 3, 3, 2), (3, 3, 1, 2, 3), (1, 3, 2, 3, 2), (3, 3, 2, 3, 1), (3, 1, 3, 2, 2), (2, 1, 3, 1, 1), (1, 1, 2, 3, 3), (2, 1, 3, 1, 2), (1, 3, 2, 1, 2), (1, 2, 1, 2, 3), (3, 2, 2, 1, 2), (3, 1, 1, 2, 2), (2, 2, 1, 3, 2), (2, 3, 2, 3, 1), (1, 1, 1, 3, 2), (2, 3, 1, 2, 1), (1, 2, 3, 1, 3), (2, 3, 1, 1, 1), (1, 2, 3, 2, 3), (2, 1, 2, 3, 3), (3, 2, 1, 2, 3), (1, 2, 2, 2, 3), (3, 2, 1, 2, 1), (2, 1, 1, 1, 3), (1, 3, 2, 3, 3), (1, 1, 3, 3, 2), (3, 2, 2, 3, 1), (3, 1, 3, 2, 3), (2, 1, 2, 1, 3), (1, 3, 3, 3, 2), (3, 2, 3, 3, 1), (2, 2, 3, 1, 3), (3, 2, 1, 1, 1), (2, 1, 3, 1, 3), (1, 2, 1, 3, 2), (3, 3, 1, 3, 2), (1, 3, 2, 1, 3), (2, 3, 1, 3, 2), (3, 1, 1, 2, 3), (2, 3, 3, 3, 1), (1, 1, 3, 2, 1), (2, 3, 1, 1, 2), (1, 2, 3, 2, 2), (2, 1, 2, 3, 2), (1, 3, 1, 1, 2), (3, 1, 3, 3, 2), (3, 1, 2, 2, 2), (3, 3, 1, 2, 1), (3, 3, 3, 1, 2), (3, 2, 3, 1, 3), (1, 3, 1, 3, 2), (2, 3, 2, 1, 3), (2, 1, 3, 3, 3), (1, 2, 2, 3, 1), (2, 3, 1, 3, 3), (1, 2, 3, 3, 1), (2, 3, 1, 2, 2), (3, 3, 2, 1, 2), (2, 3, 1, 3, 1), (3, 2, 1, 3, 3), (1, 1, 3, 2, 2), (2, 3, 1, 1, 3), (2, 1, 2, 3, 1), (1, 2, 3, 3, 3), (1, 3, 1, 2, 1), (3, 1, 2, 2, 3), (3, 1, 2, 2, 1), (2, 1, 3, 3, 1), (3, 1, 2, 1, 1), (1, 3, 2, 3, 1), (1, 2, 3, 1, 2), (3, 1, 3, 2, 1), (2, 2, 1, 2, 3), (2, 3, 2, 1, 2), (3, 3, 3, 2, 1), (2, 2, 3, 1, 1)])
请注意,这会非常快速地组合爆炸,但是因为itertools.combinations_with_replacement
和itertools.permutations
都会返回生成器,所以您还可以yield
结果。你也可以递归地自己写,但我个人认为这不太令人满意。
我相信在这里使用distinct_permutations
也足够了,你最终得到一个完全不同的结果列表,因为外部循环的每次迭代都会产生不同的频率签名元素。
答案 1 :(得分:0)
这是一个额外的解决方案,它也以字母顺序迭代。
import itertools
def _recurse_extended_perm(remaining,inputList,requireList):
if remaining==len(requireList):
for p in itertools.permutations(requireList):
yield p
elif remaining==1:
for x in inputList:
yield [x]
else:
for x in inputList:
req = list(requireList)
if x in req:
req.remove(x)
for seq in _recurse_extended_perm(remaining-1,inputList,req):
out = [x]
out.extend(seq)
yield out
def extended_permutation(seq,k):
inputList = list(seq)
inputList.sort()
assert(k>len(inputList))
for seq in _recurse_extended_perm(k,inputList,inputList):
yield tuple(seq)
答案 2 :(得分:0)
我们可以递归地生成列表。这是一个无模块实现,也为我们提供了一点灵活性:
def multisets_with_at_least_m(inputList, k, m):
def f(idx, n, multiset):
if idx == len(inputList):
return [multiset]
if (len(inputList) - idx) * m > n:
return []
minNum = n if idx == len(inputList) - 1 else m
maxNum = n - (len(inputList) - idx) * m + m
results = []
for i in xrange(minNum, maxNum + 1):
multisetCopy = multiset.copy()
multisetCopy[inputList[idx]] = i
results = results + f(idx + 1, n - i, multisetCopy)
return results
return f(0, k, {})
def distinct_permutations_from_multiset(multiset):
def f(multiset, permutation):
if multiset == {}:
return [permutation]
results = []
for k in multiset:
multisetCopy = multiset.copy()
if multiset[k] == 1:
del multisetCopy[k]
else:
multisetCopy[k] = multisetCopy[k] - 1
results = results + f(multisetCopy, permutation + [k])
return results
return f(multiset, [])
输出:
print [distinct_permutations_from_multiset(x) for x in multisets_with_at_least_m([1,2,3], 5, 1)]
"""
[[[1, 2, 3, 3, 3], [1, 3, 2, 3, 3], [1, 3, 3, 2, 3], [1, 3, 3, 3, 2]
, [2, 1, 3, 3, 3], [2, 3, 1, 3, 3], [2, 3, 3, 1, 3], [2, 3, 3, 3, 1]
, [3, 1, 2, 3, 3], [3, 1, 3, 2, 3], [3, 1, 3, 3, 2], [3, 2, 1, 3, 3]
, [3, 2, 3, 1, 3], [3, 2, 3, 3, 1], [3, 3, 1, 2, 3], [3, 3, 1, 3, 2]
, [3, 3, 2, 1, 3], [3, 3, 2, 3, 1], [3, 3, 3, 1, 2], [3, 3, 3, 2, 1]]
, [[1, 2, 2, 3, 3], [1, 2, 3, 2, 3], [1, 2, 3, 3, 2], [1, 3, 2, 2, 3]
, [1, 3, 2, 3, 2], [1, 3, 3, 2, 2], [2, 1, 2, 3, 3], [2, 1, 3, 2, 3]
, [2, 1, 3, 3, 2], [2, 2, 1, 3, 3], [2, 2, 3, 1, 3], [2, 2, 3, 3, 1]
, [2, 3, 1, 2, 3], [2, 3, 1, 3, 2], [2, 3, 2, 1, 3], [2, 3, 2, 3, 1]
, [2, 3, 3, 1, 2], [2, 3, 3, 2, 1], [3, 1, 2, 2, 3], [3, 1, 2, 3, 2]
, [3, 1, 3, 2, 2], [3, 2, 1, 2, 3], [3, 2, 1, 3, 2], [3, 2, 2, 1, 3]
, [3, 2, 2, 3, 1], [3, 2, 3, 1, 2], [3, 2, 3, 2, 1], [3, 3, 1, 2, 2]
, [3, 3, 2, 1, 2], [3, 3, 2, 2, 1]]
, [[1, 2, 2, 2, 3], [1, 2, 2, 3, 2], [1, 2, 3, 2, 2], [1, 3, 2, 2, 2]
, [2, 1, 2, 2, 3], [2, 1, 2, 3, 2], [2, 1, 3, 2, 2], [2, 2, 1, 2, 3]
, [2, 2, 1, 3, 2], [2, 2, 2, 1, 3], [2, 2, 2, 3, 1], [2, 2, 3, 1, 2]
, [2, 2, 3, 2, 1], [2, 3, 1, 2, 2], [2, 3, 2, 1, 2], [2, 3, 2, 2, 1]
, [3, 1, 2, 2, 2], [3, 2, 1, 2, 2], [3, 2, 2, 1, 2], [3, 2, 2, 2, 1]]
, [[1, 1, 2, 3, 3], [1, 1, 3, 2, 3], [1, 1, 3, 3, 2], [1, 2, 1, 3, 3]
, [1, 2, 3, 1, 3], [1, 2, 3, 3, 1], [1, 3, 1, 2, 3], [1, 3, 1, 3, 2]
, [1, 3, 2, 1, 3], [1, 3, 2, 3, 1], [1, 3, 3, 1, 2], [1, 3, 3, 2, 1]
, [2, 1, 1, 3, 3], [2, 1, 3, 1, 3], [2, 1, 3, 3, 1], [2, 3, 1, 1, 3]
, [2, 3, 1, 3, 1], [2, 3, 3, 1, 1], [3, 1, 1, 2, 3], [3, 1, 1, 3, 2]
, [3, 1, 2, 1, 3], [3, 1, 2, 3, 1], [3, 1, 3, 1, 2], [3, 1, 3, 2, 1]
, [3, 2, 1, 1, 3], [3, 2, 1, 3, 1], [3, 2, 3, 1, 1], [3, 3, 1, 1, 2]
, [3, 3, 1, 2, 1], [3, 3, 2, 1, 1]]
, [[1, 1, 2, 2, 3], [1, 1, 2, 3, 2], [1, 1, 3, 2, 2], [1, 2, 1, 2, 3]
, [1, 2, 1, 3, 2], [1, 2, 2, 1, 3], [1, 2, 2, 3, 1], [1, 2, 3, 1, 2]
, [1, 2, 3, 2, 1], [1, 3, 1, 2, 2], [1, 3, 2, 1, 2], [1, 3, 2, 2, 1]
, [2, 1, 1, 2, 3], [2, 1, 1, 3, 2], [2, 1, 2, 1, 3], [2, 1, 2, 3, 1]
, [2, 1, 3, 1, 2], [2, 1, 3, 2, 1], [2, 2, 1, 1, 3], [2, 2, 1, 3, 1]
, [2, 2, 3, 1, 1], [2, 3, 1, 1, 2], [2, 3, 1, 2, 1], [2, 3, 2, 1, 1]
, [3, 1, 1, 2, 2], [3, 1, 2, 1, 2], [3, 1, 2, 2, 1], [3, 2, 1, 1, 2]
, [3, 2, 1, 2, 1], [3, 2, 2, 1, 1]]
, [[1, 1, 1, 2, 3], [1, 1, 1, 3, 2], [1, 1, 2, 1, 3], [1, 1, 2, 3, 1]
, [1, 1, 3, 1, 2], [1, 1, 3, 2, 1], [1, 2, 1, 1, 3], [1, 2, 1, 3, 1]
, [1, 2, 3, 1, 1], [1, 3, 1, 1, 2], [1, 3, 1, 2, 1], [1, 3, 2, 1, 1]
, [2, 1, 1, 1, 3], [2, 1, 1, 3, 1], [2, 1, 3, 1, 1], [2, 3, 1, 1, 1]
, [3, 1, 1, 1, 2], [3, 1, 1, 2, 1], [3, 1, 2, 1, 1], [3, 2, 1, 1, 1]]]
"""