Grid Robot Command Simulator
Company: Shopify
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question tests practical coding ability by requiring implementation of a command-driven state machine on a bounded 2D grid. It evaluates simulation logic, boundary handling, and input parsing — skills commonly assessed in software engineering interviews to gauge attention to edge cases and clean state management.
Grid Robot Command Simulator
Constraints
- 1 <= W, H <= 1000
- Number of command lines <= 100000
- PLACE coordinates fit in a 32-bit signed integer but may be out of grid bounds (then the PLACE is ignored)
- Commands are case-sensitive and exactly as specified
Examples
Input: ([5, 5], ['PLACE 0 0 N', 'MOVE', 'REPORT', 'LEFT', 'REPORT', 'MOVE', 'REPORT'])
Expected Output: ['0,1,N', '0,1,W', '0,1,W']
Explanation: Placed at (0,0) facing N, MOVE -> (0,1). LEFT from N gives W. The final MOVE faces W from column 0, which would leave the grid, so it is ignored.
Input: ([3, 3], ['REPORT', 'MOVE', 'PLACE 1 1 E', 'REPORT'])
Expected Output: ['1,1,E']
Explanation: REPORT and MOVE before the first valid PLACE are ignored and produce no output; only the post-PLACE REPORT prints.
Input: ([5, 5], ['PLACE 4 4 N', 'MOVE', 'RIGHT', 'MOVE', 'REPORT'])
Expected Output: ['4,4,E']
Explanation: At the top-right corner facing N, MOVE off the top edge is ignored. RIGHT turns to E; MOVE off the right edge is also ignored, so the robot stays at (4,4,E).
Input: ([1, 1], ['PLACE 0 0 S', 'MOVE', 'MOVE', 'REPORT', 'RIGHT', 'REPORT'])
Expected Output: ['0,0,S', '0,0,W']
Explanation: On a 1x1 grid every MOVE is off-grid, so position never changes; RIGHT from S yields W.
Input: ([5, 5], ['PLACE 2 2 N', 'GARBAGE', 'PLACE 9 9 N', 'PLACE 0 0 X', 'REPORT'])
Expected Output: ['2,2,N']
Explanation: An unrecognized line, an out-of-grid PLACE, and a PLACE with an invalid direction are all ignored, leaving the robot at (2,2,N).
Input: ([10, 10], ['PLACE 5 5 W', 'LEFT', 'LEFT', 'LEFT', 'LEFT', 'REPORT', 'MOVE', 'REPORT'])
Expected Output: ['5,5,W', '4,5,W']
Explanation: Four LEFT turns return to the original heading W; the interior MOVE west succeeds to (4,5).
Input: ([2, 2], [])
Expected Output: []
Explanation: No commands means no output.
Hints
- Track three pieces of state: position (x, y), heading, and a boolean for whether the robot has been placed. Ignore every non-PLACE command while unplaced.
- Encode the four headings with unit direction vectors (N=(0,1), E=(1,0), S=(0,-1), W=(-1,0)) so MOVE is just an add, and use two small lookup tables for LEFT/RIGHT rotations.
- Validate aggressively: a PLACE outside the grid or with a bad direction, and a MOVE that would leave the grid, must be no-ops. Reject malformed token counts so garbage lines never mutate state.
Grid Robot Command Simulator (Multiple Robots)
Constraints
- 1 <= W, H <= 1000
- Number of command lines <= 100000
- Robot ids are non-negative integers; a missing, negative, or non-integer id makes the line malformed and ignored
- PLACE coordinates fit in a 32-bit signed integer but may be out of grid bounds (then the PLACE is ignored)
Examples
Input: ([5, 5], ['0 PLACE 0 0 N', '0 MOVE', '0 REPORT', '0 LEFT', '0 REPORT', '0 MOVE', '0 REPORT'])
Expected Output: ['0:0,1,N', '0:0,1,W', '0:0,1,W']
Explanation: A single robot behaves exactly as in part 1, now with the id prefix in REPORT output.
Input: ([5, 5], ['0 PLACE 1 1 N', '1 PLACE 1 2 S', '1 MOVE', '1 REPORT', '0 MOVE', '0 REPORT'])
Expected Output: ['1:1,2,S', '0:1,1,N']
Explanation: Robot 1 at (1,2) facing S tries to MOVE into (1,1) held by robot 0 — collision, ignored. Robot 0 then tries to MOVE N into (1,2) held by robot 1 — also a collision, ignored. Both stay put.
Input: ([5, 5], ['0 PLACE 2 2 N', '1 PLACE 2 2 S', '1 REPORT', '0 REPORT'])
Expected Output: ['0:2,2,N']
Explanation: Robot 1's PLACE targets (2,2), already held by robot 0, so it is ignored; robot 1 stays unplaced and its REPORT produces nothing.
Input: ([5, 5], ['2 MOVE', '2 REPORT', '0 PLACE 3 3 E', '0 REPORT'])
Expected Output: ['0:3,3,E']
Explanation: Commands for robot 2 before it is placed (MOVE, REPORT) are ignored; only robot 0's REPORT after a valid PLACE prints.
Input: ([5, 5], ['0 PLACE 1 1 E', '0 PLACE 4 4 W', '0 REPORT'])
Expected Output: ['0:4,4,W']
Explanation: Re-placing robot 0 to an empty cell vacates its old cell and moves it to (4,4) facing W.
Input: ([5, 5], ['0 PLACE 1 1 N', '1 PLACE 2 2 W', '0 PLACE 2 2 S', '0 REPORT', '1 REPORT'])
Expected Output: ['0:1,1,N', '1:2,2,W']
Explanation: Robot 0's re-PLACE onto (2,2), held by robot 1, is rejected, so robot 0 stays at its prior (1,1,N) and robot 1 is unaffected.
Input: ([5, 5], ['-1 PLACE 0 0 N', 'x PLACE 1 1 N', '0 PLACE 0 0 N', '0 REPORT'])
Expected Output: ['0:0,0,N']
Explanation: A negative id and a non-integer id make those lines malformed and ignored; only the valid robot 0 is placed.
Input: ([3, 1], ['0 PLACE 0 0 E', '1 PLACE 1 0 E', '0 MOVE', '0 REPORT', '1 MOVE', '1 REPORT'])
Expected Output: ['0:0,0,E', '1:2,0,E']
Explanation: On a 3x1 strip robot 0's MOVE into (1,0) is blocked by robot 1, but once robot 1 advances to (2,0) the strip clears; robot 0 simply stayed at (0,0).
Hints
- Replace the single robot's scalar state with a map id -> (x, y, heading), and add a second map cell -> id so you can check occupancy in O(1).
- A MOVE only commits if the target is in-grid AND not in the occupied map; on commit, delete the old cell from the map and insert the new one to keep the two maps consistent.
- Decide PLACE-vs-occupancy explicitly: re-placing a robot onto its own cell is allowed (heading-only), placing onto a cell held by a different robot is rejected, and moving a robot elsewhere must vacate its previous cell before claiming the new one.