Reputation: 1797
Suppose that we have a n*n
grid. We would like to choose k << n
random cells of this grid which are not adjacent. If we simulate this grid with a 2D Numpy array containing 0
and 1
, what is the most efficient way to do this in Numpy/Python?
Valid Example:
Non-valid Example:
Upvotes: 3
Views: 870
Reputation: 32511
Here's a straightforward implementation of the rejection sampling. There may be a faster way to do the adjacency check than the query_pairs
thing (which in this case also will check for collisions), since you only want to test if there is at least one pair within this distance threshold.
import numpy as np
from scipy.spatial import cKDTree as kdtree
n = 100
k = 50
valid = False
while not valid:
# generate k grid indices
coords_flat = np.random.random_integers(0, n ** 2 - 1, size=k)
coords = np.unravel_index(coords_flat, dims=(n, n))
# test there are no adjacent cells
transposed = np.transpose(coords)
valid = len(kdtree(transposed).query_pairs(1.0)) == 0
print(coords)
Taking a look at the results:
import matplotlib.pyplot as plt
grid = np.zeros((n, n), dtype=np.bool)
grid[coords] = True
plt.imshow(grid)
plt.savefig('result.png')
Upvotes: 4
Reputation: 5797
I saw, that it was an accepted answer already, but it was a challenging task, so I solved as follows and I enjoy it, thus I gave an upvote to the question :):
import numpy as np
xy = []
x = np.random.randint(0,5)
y = np.random.randint(0,5)
xy.append((x,y))
while True:
x = np.random.randint(0,5)
y = np.random.randint(0,5)
for ii,i in enumerate(xy):
if x in [i[0]-1, i[0], i[0]+1]:
if x == i[0]:
if y in [i[1]-1, i[1], i[1]+1]:
break
else:
if ii == len(xy) - 1:
xy.append((x,y))
break
elif y == i[1]:
break
elif ii == len(xy) - 1:
xy.append((x,y))
break
if len(xy) == 3:
break
for cords in xy:
print cords
sq =np.zeros((5,5))
for cords in xy:
sq[cords] = 1
print sq
Output:
(1, 0)
(4, 4)
(4, 1)
[[ 0. 0. 0. 0. 0.]
[ 1. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 1. 0. 0. 1.]]
It always provides a random combination of non-adjacent cells. Enjoy it! :)
Upvotes: 4