我的程序需要在列表列表中包含2和0的所有组合。例如:[[0,0,0,2],[0,0,2,0],[0,2,0,0] ....]。我将在每个子列表中始终有n ^ 2个元素,其中n-1次为2。所以我应该有n ^ 2!/((n ^ 2-n)!*(n-1)!)结果。
问题是我的代码首先计算所有排列,然后删除重复项。因此,对于n = 4,将有16个!子列表,它崩溃了我的电脑。我怎样才能解决这个问题? (它需要处理至少n = 8)
以下是代码:
servers = n*n #number of elements in each sublist
infected = n - 1 #number of 2s
grid = [ 0 for a in range(servers)] #list representing grid, with all 0s
grid = grid[:-infected] + infected * [2] #make last ones 2s
all_infections = list(itertools.permutations(grid)) # !!PROBLEM!! create all permutations of infection (touple)
all_infections = [list(a) for a in all_infections] # Convert touple to lists
all_infections.sort()
all_infections = list(k for k,_ in itertools.groupby(all_infections)) #remove duplicates
combinations = len(all_infections)
print (all_infections)
results = []
for index in range(combinations): #calculate the infected states
results = results + [grid_infecter(all_infections[index],n)]
答案 0 :(得分:1)
你的主要问题是远远超出实际问题要求的组合爆炸。正如你所说,n = 8的情况只需要64!/(57!7!)的结果。为什么要一次性存储它们?
这给你两个基本选择:
像这样:
def no_duplicate(gen):
previous = set()
for permutation in gen:
if permutation not in previous:
previous.add(permutation)
yield permutation
# Now set up a generator pipeline for the permutations
infection_stream = (no_duplicate(itertools.permutations(grid)))
result_stream = (grid_infecter(dish) for dish in infection_stream)
result_stream是一个可以用于任何目的的生成器,例如:
results = [_ for _ in result_stream]
生成器的神奇之处在于,到目前为止,我们在任何时候都只有一个活跃的排列。独特的存储在"之前的"在no_duplicates中设置,但这是唯一存在潜在空间问题的地方。如果这超出了你的计算机内存或你的耐心(毕竟算法是O(n ^ 2!),那么你需要编写自己的排列生成器,这样你就可以一次一个地处理它们一个长期的"记住"设备。