Evan Porter
Evan Porter

Reputation: 15

Python: How To Recursively Simulate a Random Walk Within a Range (No Loops)

A friend bet me I couldn't write this recursively. Unfortunately he won, but I am still wondering how I would go about doing this:

The function is: rw_in_range(start, low, high)

The inputs are:

start - a positive int that represents the starting position of the "sleepwalker"

low - a positive int representing the leftmost position the "sleepwalker" will be allowed to wander to

high - a positive int representing the rightmost position the "sleepwalker" will be allowed to wander to

low <= start <= high

The function should simulate a random walk where the "sleepwalker" wanders within the range of positions given by the boundaries low and high.

The sleepwalker makes random steps whose sizes is given by calls to my function:

def random_step():
    """ chooses a random step (-1 or 1) and returns it.
        inputs: none! However, make sure to use parens when calling it.
                For example: random_step()
    """
    return random.choice([-1, 1])

The random walk should continue until a given step causes the "sleepwalker" to reach/go beyond one of the boundaries low or high. The function should then return the number of steps that the sleepwalker took to get to the stopping position.

For example, with the statement print((' ' * start) + 'S') in the first line, it should look like this:

>>> rw_in_range(10, 5, 15)
      S
     S
    S
   S
    S
     S
    S
   S
  S
 S

9

My function currently looks like this:

def rw_in_range(start, low, high):
    print(('' * start) + 'S')
    new_start=start + random_step()
    steps_in_rest= rw_in_range(new_start, low, high)
    if new_start==low or new_start==high: 
        return rw_in_range(new_start, low, high)

My question is, how do I fix my code to get it to run this sequence recursively? Because as it is it never returns a value.

Upvotes: 0

Views: 2696

Answers (1)

Jose Varez
Jose Varez

Reputation: 2077

Your function never return because you are calling it again on the return. Try this:

def rw_in_range(start, low, high):
    print(('' * start) + 'S')
    new_start=start + random_step()
    if new_start<low or new_start>high: 
        return False
    rw_in_range(new_start, low, high)

If you want to count the number of steps, the best way to do it is using a list, like in the next code:

import random

def random_step():
  return random.choice([-1, 1])

def rw_in_range(start, low, high, numberOfSteps):
  if start < low or start > high:
      return False
  print(' '*(low-1)+'|'+' '*(start-low) + 'S'+' '*(high-start)+'|')
  rw_in_range(start + random_step(), low, high, numberOfSteps)
  numberOfSteps[0] += 1
  return True

numberOfSteps = [0]
rw_in_range(10, 5, 15, numberOfSteps)
print numberOfSteps[0]



Output:
rw_in_range(10, 5, 15, numberOfSteps)
    |     S    |
    |    S     |
    |   S      |
    |    S     |
    |   S      |
    |  S       |
    |   S      |
    |  S       |
    |   S      |
    |  S       |
    |   S      |
    |  S       |
    |   S      |
    |  S       |
    |   S      |
    |  S       |
    |   S      |
    |  S       |
    | S        |
    |S         |
    | S        |
    |S         |

>>>print numberOfSteps[0]

22

If you want to keep the interface of the function, use this code:

def rw_in_range(start, low, high):
    print((' ' * start) + 'S')
    new_start=start + random_step()
    if new_start<low or new_start>high: 
        return 0
    numberOfSteps = rw_in_range(new_start, low, high)
    return numberOfSteps + 1

Upvotes: 5

Related Questions