我正在尝试制作一个整数分区生成器,其中顺序很重要,并且所有部分都小于k(例如,如果k = 10且n = 100,则[5, 95]
不会是有效,因为95> = 10)。我已经从this website复制了一个生成器(并对其进行了修改),其中顺序无关紧要,现在我正在尝试制作一个通过每个分区排列的生成器。
我的主要问题是创建一个接受列表(分区)并有效输出该列表排列的函数。我已经通过使用itertools排列实现了此版本的低效率版本,其中包括:
set(itertools.permutations(partition))
这是非常低效的。当partition
具有重复项时,它将遍历所有重复项。例如,当partition = [1, 1, 1, 1, 1, 1, 1]
时,itertools将遍历所有7个!当只有一个唯一排列时= 5040个分区。
如何提高效率?我将考虑n的值在10 ^ 10或更高的数量级,因此效率非常重要。
如果有帮助,请注意分区的所有部分都小于k。
编辑:我想我(主要是)知道了。不过有一个错误。
def helper(current, index, available, freqList):
if index >= len(freqList) or available == []:
yield current
return
else:
if freqList[index] != 0:
for combo in itertools.combinations(available, freqList[index]):
yield helper(new(current, index, combo), index + 1, delete(available, combo), freqList)
else:
yield helper(current, index + 1, available, freqList)
def permutations(partition, k):
#returns permutations of partition
length = len(partition)
freqList = [partition.count(i) for i in range(k)]
available = [i for i in range(length)]
return helper([0]*length, 1, available, freqList)
delete(L, T)
返回L的副本,不含T中的元素。new(L, i, T)
返回L的副本,但T中的所有索引均被i替换。
这基本上是通过组合每个数字可以到达的位置来进行迭代。假设分区中有10 1s,5 2s和7 3s。迭代1可能经过的空间。然后,假设1占用其他空间,它将遍历2可以经过的空间。最后,在1和2占据其空间的情况下,对3可以经过的空间进行迭代。
此代码有错误。出于某种原因,permutations
返回生成器的生成器,其中生成器...嵌套m次,其中m是partition
中的最大元素。例如,如果partition = [1, 1, 1, 3, 3, 3]
,我将不得不
for gen1 in permutations(partition, k):
for gen2 in gen1:
for gen3 in gen2:
for partition in gen3:
#something else
以访问分区。
我不知道如何解决这个问题,但我认为这是个问题。
编辑2:戴维斯·赫林(Davis Herring)在评论中提到,我可以简单地yield from (helper(...)
来解决此问题。我不知道我能做到这一点,而且它奏效了。我现在对这一解决方案的其他解决方案或优化很感兴趣。