kevqnp
kevqnp

Reputation: 163

Referencing a conditional random element of an array and replacing it

This is my second question post on StackOverflow relating to coding in Python/Numpy.

I feel like there is definitely some sort of function which does the pseudocode:

np.random.choice([a[i-1,j],a[i+1,j],a[i,j-1],a[i,j+1]])==0 = 9

Essentially, I would like the random function to select a cell adjacent to mine (up, down, left, right) with the value 0, and replace said cell with a 9

Unforunately, I know why the code I typed is illegal. The first half of the statement returns a True/False boolean as I have used a comparison/checking operator. I can't set this into a value 9.

If I split the code-load into two codes and used an if statement with the random.choice (looking at an adjacent element that equalled zero), then following this, I would need some sort of function or definition to recall which cell (up down left or right) did the random generator originally select, to which I can then set it to 9.

Kind Regards,

EDIT: I may as well attach a sample code, so you can simply just run this (I am including my error)

a = np.empty((6,6,))
a[:] = 0
a[2,3]=a[3,3]=a[2,4] = 1

for (i,j), value in np.ndenumerate(a):
     if a[i,j]==1:
          np.random.choice([a[i-1,j],a[i+1,j],a[i,j-1],a[i,j+1]])==0 = 9

Upvotes: 1

Views: 350

Answers (2)

logic
logic

Reputation: 1727

This is the most "basic" way of getting what you need (Adding a try/except statement provides error checking, so you can prevent any unwanted errors):

import random,numpy
a = numpy.empty((6,6,))
a[:] = 0
a[2,3]=a[3,3]=a[5,5] = 1

for (i,j), value in numpy.ndenumerate(a):
    var = 0
    if a[i,j]==1:
        while var==0:
            x=random.randrange(0,4)                   #Generate a random number
            try:      
                if x==0 and a[i-1,j]==0:              
                    a[i-1,j] =9                       #Do this if x = 0
                elif x==1 and a[i+1,j]==0:            
                    a[i+1,j] =9                       #Do this if x = 1
                elif x==2 and a[i,j-1]==0:             
                    a[i,j-1] =9                       #Do this if x = 2
                elif x==3 and a[i,j+1]==0:            
                    a[i,j+1] =9                       #Do this if x = 3
                var=1
            except:
                var=0

print a

Upvotes: 0

Oliver W.
Oliver W.

Reputation: 13459

You could select from a range of directions (up, down, left, right) that map to specific coordinate movements in the 2D array, like this:

# generate a dataset
a = np.zeros((6,6))
a[2,3]=a[3,3]=a[2,4] = 1

# map directions to coordinate movements
nesw_map = {'left': [-1, 0], 'top': [0, 1], 'right': [1,0], 'bottom': [0,-1]}
directions = nesw_map.keys()

# select only those places where a == 1
for col_ind, row_ind in zip(*np.where(a == 1)):  # more efficient than iterating over the entire array
    x = np.random.choice(directions)
    elm_coords = col_ind + nesw_map[x][0], row_ind + nesw_map[x][1]
    if a[elm_coords] == 0:
        a[elm_coords] = 9

Note that this does not do any type of bounds checking (so if a 1 appears at the edge, you might select an item "off the grid" which will result in an error).

Upvotes: 1

Related Questions