所以,我正在生成一个空格数组,它们具有红色或黑色的属性。但是,我想防止红色被黑色包围。我有一些例子来说明我的意思:
0 0 0 0 0 0 0 1
0 1 0 0 0 0 1 0
1 0 1 0 0 0 0 1
0 1 0 0 1 1 1 0
0 0 0 0 1 0 1 0
1 1 1 0 1 1 1 0
0 0 1 0 0 0 0 0
0 0 1 0 0 0 0 0
如果红色为0且黑色为1,那么这些都是有效的外壳,我想在生成数组时避免使用它们。我有的输入是数组的大小和我可以生成的1的数量。
我将如何做到这一点?
答案 0 :(得分:2)
所以你可以做到以下几点:
条件适用于全零数组。它适用于任何迭代。因此,通过归纳,最终阵列也是如此。
在步骤4中,您可以决定是停止还是继续执行,比如说N = a * b * 1000次迭代或红色/黑色比率是否接近1.在这两种情况下,结果都会略有偏差你从全零开始。
现在,什么是条件。您必须确保连接所有黑点并连接所有红点。换句话说,最多有2个连接的集群。翻转颜色可以创建更多连接的群集,因此只有在其数量为一或两个时才会翻转。您可以使用Union-Find算法described here非常有效地进行检查。
编辑:如果您想要允许黑点被红色点包围但反之亦然,您可以将条件更改为具有任意数量的黑色簇,但只有0或1个红色簇。
答案 1 :(得分:2)
此代码是否适合您?
基本上我从左到右,从上到下填充矩阵
当我必须为一个单元格分配0或1时,我检查(北和西)是否添加1可以包含0;在这种情况下,我把0,否则随机0或1。
web.config
示例运行:import sys, random
n = int(sys.argv[1])
m = int(sys.argv[2])
# fill matrix with zeroes
matrix = [[0 for _ in xrange(m)] for _ in xrange(n)]
# functions to get north, south, west and east
# cell wrt this cell.
# If we are going out of bounds, we suppose the matrix
# is sorrounded by 1s.
def get_n(r, c):
if r <= 0: return 1
return matrix[r - 1][c]
def get_s(r, c):
if r >= n - 1: return 1
return matrix[r + 1][c]
def get_w(r, c):
if c <= 0: return 1
return matrix[r][c - 1]
def get_e(r, c):
if c >= m - 1: return 1
return matrix[r][c + 1]
# Checks if the cell is already enclosed by 3 1s.
def enclosed(r, c):
enclosing = get_n(r, c) + get_s(r, c) + get_w(r, c) + get_e(r, c)
if (enclosing > 3): raise Exception('Got a 0 enclosed by 1s')
return enclosing == 3
for r in xrange(n):
for c in xrange(m):
# check west and north
if enclosed(r, c - 1) or enclosed(r - 1, c):
matrix[r][c] = 0
else:
matrix[r][c] = random.randint(0, 1)
print str(matrix[r][c]) + ' ',
print ''
答案 2 :(得分:1)
这可能是检查条件的可能方法:
def: findStart(myArr):
for i in range(len(myArr)):
for j in range(len(myArr[0])):
if(myArr[i][j] == 0):
return (i,j)
def: checkCon(myArr, number_Ones):
width = len(myArr[0])
height = len(myArr)
pen = [] #A list of all points that are waiting to get a visit
vis = [] #A list of all points that are already visited
x = findStart(myArr)
while(len(pen) != 0): #Visit points as long as there are points left
p = pen.pop() #Pick a point to visit
if p in vis:
#do nothing since this point already was visited
else:
vis.append(p)
x,y = p
#A vertical check
if(x == 0 and myArr[x+1][y] == 0):
pen.append((x+1,y))
elif(x == (height-1) and myArr[x-1][y] == 0):
pen.append((x-1,y))
else:
if(myArr[x-1][y] == 0 and x-1 >= 0):
pen.append((x-1,y))
if(myArr[x+1][y] == 0):
pen.append((x+1,y))
#A horizontal check
if(y == 0 and myArr[x][y+1] == 0):
pen.append((x,y+1))
elif(y == (width-1) and myArr[x][y-1] == 0):
pen.append((x,y-1))
else:
if(myArr[x][y+1] == 0):
pen.append((x,y+1))
if(myArr[x][y-1] == 0 and y-1 >= 0):
pen.append((x,y-1))
print((height*width-number_Ones) == len(vis)) #if true, alle Zeros are connected and not enclosed
澄清这只是一个检查条件的概念。想法是访问所有连接的零并查看是否有任何左(未连接)。如果是这种情况,可以附上一些 当1在矩阵周围形成一个框架时,这种方法也不起作用:
1 1 1 1
1 0 0 1
1 0 0 1
1 1 1 1
再一次,只是一个概念:)
答案 3 :(得分:0)
问题实际上有两个部分。生成板状态,然后检查它是否正确。我意识到检查正确性实际上比仅确保始终生成正确的状态更糟糕。这就是我所做的:
请注意,我已将self.WallSpaces
定义为一个长度与数组高度相等的数组,由整数组成,其位数等于数组的宽度。 self.Width
和self.Height
提供数组的结束索引。基本上,Intersects
通过检查点周围的所有空间1s来工作,除了空间的方向&#34;从&#34; (见下文)并返回True
如果其中任何一个是数组的边缘或1。
def Intersects(self, point, direction):
if (point[0] > 0):
if (direction != [1, 0] and self.WallSpaces[point[0] - 1] & (1 << point[1]) != 0):
return True
if (point[1] == 0 or self.WallSpaces[point[0] - 1] & (1 << (point[1] - 1)) != 0):
return True
if (point[1] == self.Width or self.WallSpaces[point[0] - 1] & (1 << (point[1] + 1)) != 0):
return True
else:
return True
if (point[0] < self.Height):
if (direction != [-1, 0] and self.WallSpaces[point[0] + 1] & (1 << point[1]) != 0):
return True
if (point[1] == 0 or self.WallSpaces[point[0] + 1] & (1 << (point[1] - 1)) != 0):
return True
if (point[1] == self.Width or self.WallSpaces[point[0] + 1] & (1 << (point[1] + 1)) != 0):
return True
else:
return True
if (point[1] == 0 or (direction != [0, 1] and self.WallSpaces[ point[0] ] & (1 << (point[1] - 1)) != 0)):
return True
if (point[1] == self.Width or (direction != [0, -1] and self.WallSpaces[ point[0] ] & (1 << (point[1] + 1)) != 0)):
return True
return False
路线GPacW.Left
,GPacW.Right
,GPackW.Up
和GPacW.Down
代表了移动的主要方向。这个功能通过构建&#34;墙壁来实现。在随机点的数组中,可以随机转向,当它们相交两次时结束。
def BuildWalls(self):
numWalls = 0
directions = [ [GPacW.Left, GPacW.Right], [GPacW.Up, GPacW.Down] ]
start = [ random.randint(0, self.Height), random.randint(0, self.Width) ]
length = 0
horizontalOrVertical = random.randint(0, 1)
direction = random.randint(0, 1)
d = directions[horizontalOrVertical][direction]
intersected = False
while (numWalls < self.Walls):
while (start == [0, 0] or start == [self.Height, self.Width] or self.Intersects(start, d)):
start = [ random.randint(0, self.Height), random.randint(0, self.Width) ]
if (length == 0):
horizontalOrVertical = not horizontalOrVertical
direction = random.randint(0, 1)
length = random.randint(3, min(self.Height, self.Width))
d = directions[horizontalOrVertical][direction]
if (self.WallSpaces[ start[0] ] & (1 << start[1] ) == 0):
self.WallSpaces[ start[0] ] |= 1 << start[1]
numWalls += 1
length -= 1
if (0 <= (start[0] + d[0]) <= self.Height and 0 <= (start[1] + d[1]) <= self.Width):
start[0] += d[0]
start[1] += d[1]
else:
start = [0,0]
if (self.Intersects(start, d)):
if (intersected):
intersected = False
start = [0,0]
length = 0
else:
intersected = True
return