Amazing - part 5

5. More complications

Consider the following world

around the world: start

Does the program written previously work with it? Try it!

As you probably guessed, if you didn't try it (you should, really!), it does not. To make it work, we need to replace the if we just added by a while. Try it! Make sure to save it.


6. Clarifying our intent

We seem to have designed a program that works in all situations we are likely to encounter. This program, before we forget, is to allow Reeborg to explore his world, going around once. While the program is rather short, and its structure should be clear at this point, it might not be so obvious to someone who just happened to see it for the first time. It's probably a good idea to either add comments and/or introduce more meaningful words. Let's start by adding comments, somewhat more verbose than we think we might need.

# we define a useful instruction
def turn_right():
    repeat(turn_left, 3)

# we mark the starting point by putting down a beeper
put_beeper()

# We then find a clear direction and start moving.
while not front_is_clear():
    turn_left()
move()

# We know we have gone around the world
# when we come back to the beeper we put down.

while not next_to_a_beeper():
    if right_is_clear(): # keep to the right
        turn_right()
        move()
    elif front_is_clear(): # move following the right wall
        move()
    else: # follow the wall by turning left
        turn_left()

turn_off()

While this sort of clarifies our intent for each instruction, it is not really that helpful in summarizing the method (also known as the algorithm) used in solving the problem. Therefore, these comments might not be as helpful to another reader as we might have wished. Reading over the comments, we note that the program has two parts:
1) mark the starting point;
2) follow the right wall until we come back to the start.
Let's rewrite this program so that these two parts become clearer, and writing the comments differently.

# This program instructs Reeborg to go around his world
# counterclockwise, stopping when he comes 
# back to his starting point.

def turn_right():
    repeat(turn_left, 3)

def mark_starting_point_and_move():
    put_beeper()
    while not front_is_clear():
        turn_left()
    move()

def follow_right_wall():
    if right_is_clear(): 
        turn_right()
        move()
    elif front_is_clear(): 
        move()
    else: 
        turn_left()

found_starting_point = next_to_a_beeper	# beeper marks the starting point.

#=== End of definitions; begin solution

mark_starting_point_and_move()
				
while not found_starting_point(): 
    follow_right_wall()
		
turn_off()

Isn't this clearer? Now, suppose that each corner has a beeper on it at the start. We could then choose to mark the starting point by removing a beeper. We would need to make some small changes in the definitions, but the solution as such would not need to be changed.


7. First surprise

Try the program you just wrote and save with the following hurdle race (file: hurdles3.wld).

hurdles

Surprise! Other than finishing facing in an unusual direction (perhaps bowing to the crowd after winning), the program we just wrote can solve the hurdle problem. It also works with the uneven hurdle (file: hurdles4.wld) illustrated below - which the program we wrote before for jumping over hurdles could not handle!

hurdles

You might even note that we don't need mark_starting_point_and_move() in this case. Because we structured our program clearly, it would be very easy to remove that instruction, and its definition, and save the program under a different, more descriptive name (racing_hurdles perhaps).


8. Amazing surprise

Try the same program again with the maze problem we introduced in chapter 1 (file: maze1.wld), illustrated below.

maze

As you will see, our simple program can find the exit to this maze! Amazing! Once again, we note that we have a superfluous instruction.


9. Conclusion

We started with a simple problem to solve (going around a rectangular world) and, by improving little by little (also called stepwise refinement), we manage to write a program that could be used to solve many other apparently unrelated problems. At each step, we kept the changes small, and made sure we had a working solution, before considering more complex problems. We also used more descriptive names for parts of the algorithm which made the program easier to read and, hopefully, to understand. This is a strategy you should use when writing your own programs:

previous Amazing - part4 - home - It's raining! next
../images/SourceForge.net Logo