Terminal-Controlled Grid Rover Simulator
ShopifySoftware Engineer · Technical ScreenLast updated
Implement a warehouse rover simulation engine that processes sequential movement commands on a bounded 2D grid, handling coordinate translations, cardinal rotations, boundary limits, and multi-rover collision avoidance.
Problem Statement
In an automated fulfillment warehouse, a fleet of robotic rovers navigates a bounded 2D grid floor. You are tasked with implementing a simulation engine that processes sequential navigation commands for multiple rovers.
The warehouse grid spans from coordinate (0, 0) (bottom-left corner) to (width - 1, height - 1) (top-right corner).
Each rover is initialized with a starting position (x, y) and a cardinal orientation ('N', 'E', 'S', or 'W'). Rovers are deployed sequentially: a rover processes its complete command sequence before the next rover begins. Once a rover completes its instructions, it parks at its final location and acts as an obstacle for subsequent rovers.
Rovers receive a string of instruction characters:
'L': Rotate 90 degrees counter-clockwise (e.g.,'N'becomes'W').'R': Rotate 90 degrees clockwise (e.g.,'N'becomes'E').'M': Move forward 1 grid unit in the current orientation.
Collision & Boundary Rules
- If a rover attempts to move into a cell that is outside the grid boundaries (
x = width,y = height), the movement is ignored and the rover remains in its current cell. - If a rover attempts to move into a cell occupied by a previously parked rover, the movement is ignored and the rover remains in its current cell.
- In both cases, the rover continues executing any remaining instructions.
Implement the function simulate_rovers.
Function Signature
def simulate_rovers(
width: int,
height: int,
rovers: list[tuple[int, int, str, str]]
) -> list[tuple[int, int, str]]:
pass
Input
width: Integer representing grid width along the x-axis.height: Integer representing grid height along the y-axis.rovers: A list of tuples(x, y, orientation, commands)for each rover, in order of execution.
Output
- Return a list of tuples
(final_x, final_y, final_orientation)for each rover in the order they were processed.
Constraints
1 <= width, height <= 10000 <= len(rovers) <= 5000 <= len(commands) <= 10^4per rover0 <= x < widthand0 <= y < heightfor initial rover positions.- Initial rover positions are guaranteed to not collide with previously parked rovers.
Example 1
width = 5
height = 5
rovers = [
(1, 2, 'N', "LMLMLMLMM"),
(3, 3, 'E', "MMRMMRMRRM")
]
output = simulate_rovers(width, height, rovers)
# Output: [(1, 3, 'N'), (5, 1, 'E')] -- wait, 5 is out of bounds!
Explanation for Example 1:
Grid is 5x5 (0 <= x <= 4, 0 <= y <= 4).
- Rover 1 starts at
(1, 2, 'N'). Executing"LMLMLMLMM"moves it to(1, 3, 'N'). - Rover 1 parks at
(1, 3). - Rover 2 starts at
(3, 3, 'E'). It moves East:(4, 3), then tries to move East again to5, butx=5is out of bounds, so it stays at(4, 3). It turns South ('R'), moves to(4, 2), then(4, 1). Turns West ('R'), moves to(3, 1). Turns North ('R'), turns East ('R'), moves to(4, 1). Rover 2 ends at(4, 1, 'E').
Edge Cases
- Empty list of rovers returns
[]. - Rover given commands that repeatedly hit boundary limits.
- Rover attempting to cross the position of an already parked rover.
Hints
Hint 1
Represent cardinal directions in clockwise order (e.g., ['N', 'E', 'S', 'W']) so that 'L' and 'R' can be computed using modulo arithmetic.
Hint 2
Map each cardinal direction to coordinate deltas (dx, dy) to simplify forward movements.
Hint 3
Maintain a set of occupied coordinates for parked rovers, checking both grid boundaries and set membership before applying 'M'.
Follow-up questions
- How would you adapt the simulation if rovers moved concurrently (turn-by-turn or time-step by time-step) rather than sequentially?
- If rovers could move backwards ('B') or diagonal moves were allowed, what modifications to your state representation would you make?
- How would you handle a deadlock situation where two moving rovers block each other's planned next steps in a concurrent execution model?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.