← Back to course
Python 11-12 / Week 06 / Tuesday
2/6
Week 06 · Drive and Test

Tuesday

Command strings
// Step by step across the field, with tests at the edges
⏱ about 30 min

Tuesday: Command Strings

Comet writes a route on a sticky note: FFRFX. "F is forward, L and R are turns," she says. "X was a typo. Pip should just stop, right?"

Wren shakes his head. "What does the evidence say we want?" he asks. "A rover that crashes on one bad letter is not ready for the field."

Nova projects the route one letter at a time, with a log growing beside it. "How can I help?" she asks. "Try logging anything Pip does not know, and keep going."

"Lead programmer," Comet says, "trace my route. Where does Pip end up, and what does the log say about X?"

The run() method

run() walks a command string one letter at a time. F calls move(), L and R turn, and anything else is logged as an unknown command.

Common security issues in programs include missing bounds checks and poor input validation. run() validates every letter instead of trusting it.

    def run(self, commands, grid):
        """Follow a command string: F forward, L left, R right."""
        for c in commands:
            if c == "F":
                self.move(grid)
            elif c == "L":
                self.turn_left()
            elif c == "R":
                self.turn_right()
            else:
                self._log.append(f"unknown command {c}")
# route.py
from field_data import FIELD
from grid import FieldGrid
from rover import Rover

grid = FieldGrid(FIELD)
pip = Rover("Pip")
pip.run("FFRFX", grid)
print(pip.status())
for line in pip.get_log():
    print(line)
LetterWhat run() doesPip after it
Fmove()(0, 1) facing E
Fmove()(0, 2) facing E
Rturn_right()(0, 2) facing S
Fmove()(1, 2) facing S
Xlogs unknown command X(1, 2) facing S
PREDICT ROUTE.PY
  • Read the question.
  • Tap your answer.
What does the status line show?
What is the last log line?
Pip at (1, 2) facing S, battery 85
moved to (0, 1)
moved to (0, 2)
moved to (1, 2)
unknown command X

Typed commands

Now the commands come from input(). The program asks only for simulation commands. Watch two runs: one typed in capitals, one in lowercase.

# drive_input.py
from field_data import FIELD
from grid import FieldGrid
from rover import Rover

grid = FieldGrid(FIELD)
pip = Rover("Pip")
commands = input("Commands (F, L, R): ")
pip.run(commands, grid)
print(pip.status())
print(pip.get_log())

Run 1, typed FFRF:

Commands (F, L, R): FFRF
Pip at (1, 2) facing S, battery 85
['moved to (0, 1)', 'moved to (0, 2)', 'moved to (1, 2)']

Run 2, typed ffrf:

Commands (F, L, R): ffrf
Pip at (0, 0) facing E, battery 100
['unknown command f', 'unknown command f', 'unknown command r', 'unknown command f']
READ THE TWO RUNS
  • Read the question.
  • Tap your answer.
Why did Pip stay at (0, 0) in run 2?

One change fixes it: add .upper() after input(...). The run below shows typed ffrf now drives like FFRF.

# drive_upper.py
from field_data import FIELD
from grid import FieldGrid
from rover import Rover

grid = FieldGrid(FIELD)
pip = Rover("Pip")
commands = input("Commands (F, L, R): ").upper()
pip.run(commands, grid)
print(pip.status())
PREDICT DRIVE_UPPER.PY
  • Read the question.
  • Tap your answer.
Typed ffrf. What does the status line show?
At your computer
1. Your rover.py gets run() on Wednesday. Today, make command_test.py in your fieldsim folder: the same idea with a heading and a log, no Rover. Type it and run it.
2. Change "RRLXF" to "LLLL". Predict the heading, then run it.
3. Delete the colon after else and run it. Read the SyntaxError calmly: it points at the line. Then put the colon back.
# command_test.py
HEADINGS = ["N", "E", "S", "W"]

heading = "E"
log = []
for c in "RRLXF":
    if c == "L":
        i = HEADINGS.index(heading)
        heading = HEADINGS[(i - 1) % 4]
    elif c == "R":
        i = HEADINGS.index(heading)
        heading = HEADINGS[(i + 1) % 4]
    elif c == "F":
        log.append(f"forward facing {heading}")
    else:
        log.append(f"unknown command {c}")
print(heading)
print(log)
TRACE COMMAND_TEST.PY
  • Read the question.
  • Tap your answer.
What heading does command_test.py print?
What is the first item in the log?

Pip can follow orders and stay calm about typos. Tomorrow you build the final rover.py.

← Monday