A simple "turtle'' virtual robot lives on an infinite two-dimensional plane on which its location is always an integer pair of $(x,y)$ co-ordinates. It can face only in directions parallel to the $x$ and $y$ axes (i.e. 'North', 'East', 'South' or 'West') and it understands four commands:
F
: move forward one unit;L
: turn left (anti-clockwise) by $90^\circ$;R
: turn right (clockwise) by $90^\circ$;S
: stop and exit.The following Python program takes a list of such commands as a string and tracks the turtle's location. The turtle starts at $(0,0)$, facing in the direction $(1,0)$ ('East'). The program ignores (but warns about) invalid commands, and reports when the turtle crosses its own path.
commands = 'FFFFFLFFFLFFFFRRRFXFFFFFFS'
# Current location, current facing direction
x, y = 0, 0
dx, dy = 1, 0
# Keep track of the turtle's location in the list of tuples, locs
locs = [(0, 0)]
for cmd in commands:
if cmd == 'S':
# Stop command
break
if cmd == 'F':
# Move forward in the current direction
x += dx
y += dy
if (x, y) in locs:
print('Path crosses itself at: ({}, {})'.format(x,y))
locs.append((x,y))
continue
if cmd == 'L':
# Turn to the left (counterclockwise).
# L => (dx, dy): (1,0) -> (0, 1) -> (-1,0) -> (0,-1) -> (1,0)
dx, dy = -dy, dx
continue
if cmd == 'R':
# Turn to the right (clockwise).
# R => (dx, dy): (1,0) -> (0,-1) -> (-1,0) -> (0, 1) -> (1,0)
dx, dy = dy, -dx
continue
# if we're here it's because we don't recognise the command: warn
print('Unknown command:', cmd)
else:
# We exhausted the commands without encountering an S for STOP
print('Instructions ended without a STOP')
# Plot a path of asterisks
# First find the total range of x and y values encountered
x, y = zip(*locs)
xmin, xmax = min(x), max(x)
ymin, ymax = min(y), max(y)
# The grid size needed for the plot is (nx, ny)
nx = xmax - xmin + 1
ny = ymax - ymin + 1
# Reverse the y-axis so that it decreases *down* the screen
for iy in reversed(range(ny)):
for ix in range(nx):
if (ix+xmin, iy+ymin) in locs:
print('*', end='')
else:
print(' ', end='')
print()
Some notes:
We can iterate over the string commands
to take its characters one at a time.
The else:
clause to the for
loop is only executed if we do not break
out of it on encountering a STOP command.
We unzip the list of tuples, locs
, into separate sequences of the $x$ and $y$ coordinates with zip(*locs)
.
The output produced from the commands given is:
Unknown command: X
Path crosses itself at: (1, 0)
*****
* *
* *
******
*
*
*
*