【发布时间】:2019-09-07 01:44:39
【问题描述】:
我想写一个函数my_func(n,l),对于一些正整数n,有效地枚举长度为l的有序非负整数组合*(其中l大于n) .比如我想让my_func(2,3)返回[[0,0,2],[0,2,0],[2,0,0],[1,1,0],[1,0,1],[0,1,1]]。
我最初的想法是将现有代码用于正整数分区(例如 this post 中的 accel_asc()),将正整数分区扩展几个零并返回所有排列。
def my_func(n, l):
for ip in accel_asc(n):
nic = numpy.zeros(l, dtype=int)
nic[:len(ip)] = ip
for p in itertools.permutations(nic):
yield p
这个函数的输出是错误的,因为每个数字出现两次(或多次)的非负整数组合在my_func的输出中出现了多次。例如,list(my_func(2,3)) 返回[(1, 1, 0), (1, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1), (0, 1, 1), (2, 0, 0), (2, 0, 0), (0, 2, 0), (0, 0, 2), (0, 2, 0), (0, 0, 2)]。
我可以通过生成所有非负整数组合的列表、删除重复条目、然后返回剩余列表(而不是生成器)来纠正此问题。但这似乎非常低效,并且可能会遇到内存问题。有什么更好的方法来解决这个问题?
编辑
我对这篇文章和 cglacet 在 cmets 中指出的 another post 的答案中提供的解决方案进行了快速比较。
左边是l=2*n,右边是l=n+1。在这两种情况下,user2357112 的第二个解决方案比其他解决方案更快,n<=5。对于n>5,user2357112、Nathan Verzemnieks 和 AndyP 提出的解决方案或多或少是相关的。但在考虑l 和n 之间的其他关系时,结论可能会有所不同。
.......
*我最初要求的是非负整数分区。 Joseph Wood 正确地指出,我实际上是在寻找整数组合,因为序列中数字的顺序对我很重要。
【问题讨论】:
-
@Green Cloak Guy 它仍然需要在生成第一个分区之前生成所有非负整数分区。
n和l的非负整数分区的数量增长得非常快,所以我真的很想避免这种情况。 -
@BadZen 该线程在 positive 整数分区上。我想要非负整数分区。
-
@AliceSchwarze:将正元素解应用于非负元素解的其他方法 - 将
n+l划分为正整数并从划分元素中减去 1。当然,这并不能解决更深层次的多集/元组问题。 -
对于它的价值,我刚刚测试了@cglacet 提到的问题中的所有解决方案,但没有一个比这里的两个更快的解决方案快,尽管this one 很接近。
-
IMO 值得一提,我不知道 Stackoverflow 在这种情况下应该如何工作,但也许最好的解决方案是合并这两个问题(因为这两个问题完全相同,除非我遗漏了什么)。
标签: python python-3.x numpy permutation combinatorics