我有这个清单:
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个元素,这需要永远想出所有可能的排列。
有没有一种有效的方法可以解决这个问题?
答案 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)