如何在列表中检查邻接,然后在python中修复邻接

时间:2014-04-08 18:23:53

标签: python algorithm list permutation

我有这个清单:

row = [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

然后我需要随机播放或随机化列表:

shuffle(row)

然后我需要经历并找到任何相邻的1并移动它们,使它们至少相隔一个0.例如,我需要将结果看起来像这样:

row = [0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0]

我不确定最有效的方法是搜索相邻的1,然后移动它们以使它们不相邻......我也会反复这样做这行的多个组合。

最初当列表较短时我就是这样做的:

row = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
rowlist = set(list(permutations(row)))
rowschemes = [(0, 0) + x for x in rowlist if '1, 1' not in str(x)]

但是现在我的行​​长达20个元素,这需要永远想出所有可能的排列。

有没有一种有效的方法可以解决这个问题?

4 个答案:

答案 0 :(得分:2)

我有一个适度聪明的基于分区的方法,但是因为你说总共有20个数字和6个1,而6是一个非常小的数字,你可以构建所有可能的位置(38760)并抛出那些这是无效的。然后你可以从那些中统一绘制,并构建结果行:

import random
from itertools import combinations

def is_valid(locs):
    return all(y-x >= 2 for x,y in zip(locs, locs[1:]))

def fill_from(size, locs):
    locs = set(locs)
    return [int(i in locs) for i in range(size)]

然后

>>> size = 20
>>> num_on = 6
>>> on_locs = list(filter(is_valid, combinations(range(size), num_on)))
>>> len(on_locs)
5005
>>> fill_from(size, random.choice(on_locs))
[0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1]
>>> fill_from(size, random.choice(on_locs))
[0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1]
>>> fill_from(size, random.choice(on_locs))
[1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1]

答案 1 :(得分:1)

为什么不直接去找你想要的?类似的东西:

row = ["0","0","0","0","0","0","0","0","0","01","01","01","01","01","01"]
random.shuffle(row)
print (map(int, list("".join(row)[1:])))

答案 2 :(得分:0)

由于1的数量固定在一行而你不希望任何1是相邻的,所以让m为1的数,让k为该行的0的数。然后,您希望随机将m 1放在(k + 1)个位置,这样每个位置最多只有1个。这等于从集合(1,2,...,k + 1)中选择大小的随机子集((k + 1)选择m)。这很容易做到。给定子集的随机选择,您可以构造0和1的随机排列,这样就不会有两个1相邻。随机选择算法需要O(m)时间。

答案 3 :(得分:0)

将6个1和5个0放在列表中

row = [1,0,1,0,1,0,1,0,1,0,1]

然后在(成长)列表中的随机位置逐个插入剩余的0。

for i in range(11,19):
    row.insert(random.randint(0,i), 0)