blandman1990
blandman1990

Reputation: 73

Manhattan grid directions with random walk

I am trying to write a function that takes the number or rows and columns in a grid, simulates a random walk starting in the center of the grid, and computes the number of times each intersection has been visited by the random walk. Then prints the table line by line once the random walk moves outside the grid So far I have this but i cant get it to work right.

def manhattan(x,y):
    'int,int==>nonetype'
    import random
    res=[]
    for i in range(x):
        res.append([])
    for i in res:
        for j in range(y):
            i.append(0)
    position=(x//2+1,y//2+1)
    z=position[0]
    v=position[1]

    while z!=-1 or z!=x or v!=-1 or v!=y:
        direction=random.randrange(1,5)
        if direction==1:
            v+=1
        elif direction==2:
            z+=1
        elif direction==3:
            v-=1
        else:
            z-=1
        for i in range(len(res)):
            if i ==z:
                res[i]+=1
            for j in range(i):
                if v==j:
                    i[j]+=1
    for i in res:
        print(i)

It should read when done:

manhattan(5,11)
[0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,1,1,1,1,2,2]
[0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0]

Upvotes: 0

Views: 2346

Answers (2)

Hooked
Hooked

Reputation: 88168

Here is a bit less verbose version that uses random.choice instead of your chained elif statements. I found it helpful when learning python to see the same problem in different ways, so here is a pure python and a numpy + python implementation.

Pure Python

import random

def manhattan(n,m):
    grid = [[0,]*m for _ in xrange(n)]
    directions = [[-1,0],[1,0],[0,-1],[0,1]]
    pt = [n//2, m//2]

    while pt[0]>=0 and pt[0]<n and pt[1]>=0 and pt[1]<m:
        grid[pt[0]][pt[1]] += 1
        d  = random.choice(directions)
        pt[0] += d[0]
        pt[1] += d[1]
    return grid

for row in manhattan(5,11):
    print row

This gives, for example,

[0, 0, 0, 1, 3, 3, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 3, 3, 2, 0, 0, 0]
[0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0]
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]

Python + numpy

import numpy as np
import random

def manhattan(n,m):
    grid = np.zeros((n,m),dtype=int)
    directions = [[-1,0],[1,0],[0,-1],[0,1]]
    pt   = np.array([n//2, m//2])

    while (pt>=0).all() and (pt<grid.shape).all():
        grid[pt[0],pt[1]]  += 1      
        pt += random.choice(directions)
    return grid

print manhattan(5,11)

Upvotes: 1

Andrew Clark
Andrew Clark

Reputation: 208505

You were very close, try the following:

def manhattan(x,y):
    'int,int==>nonetype'
    import random
    res=[]
    for i in range(x):
        res.append([])
    for i in res:
        for j in range(y):
            i.append(0)
    position=(x//2+1,y//2+1)
    z=position[0]
    v=position[1]

    while z!=-1 and z!=x and v!=-1 and v!=y:
        res[z][v] += 1
        direction=random.randrange(1,5)
        if direction==1:
            v+=1
        elif direction==2:
            z+=1
        elif direction==3:
            v-=1
        else:
            z-=1
    for i in res:
        print(i)

Nothing is different until the while loop, and there are only a couple of changes. First you need to use and instead of or in the loop condition check since you want to exit if any of those conditions are met.

The other change was to remove the for loop from the bottom of the while loop and replace it by res[z][v] += 1, this works because z and v represent the intersection and you already initialized res to be a two-dimensional list of all the intersections so looping is unnecessary. I also moved this up to the top of the loop because otherwise you might try to modify res after moving past the boundary.

Upvotes: 1

Related Questions