|
1 | 1 | # [Problem 874: Walking Robot Simulation](https://leetcode.com/problems/walking-robot-simulation/description/?envType=daily-question) |
2 | 2 |
|
3 | 3 | ## Initial thoughts (stream-of-consciousness) |
4 | | -I need to simulate the robot on an infinite grid. Commands are either turns (-2 left, -1 right) or small forward moves (1..9). There are obstacles that block movement if the robot would step onto them; then it stays in the previous cell and continues with the next command. The goal is to return the maximum squared Euclidean distance from origin encountered. |
| 4 | +We need to simulate a robot moving on an infinite grid following commands: turn left, turn right, or move forward k steps (k between 1 and 9). Some grid points are obstacles; if the robot would step onto an obstacle, that single step is blocked and the robot stops processing further steps of that command (but continues with next command). We must return the maximum squared Euclidean distance from origin reached at any time. |
5 | 5 |
|
6 | | -A straightforward simulation seems fine: keep the robot's position and direction, process each command. For movement commands, move one step at a time checking for obstacles. Obstacle lookups should be O(1), so store obstacles in a hash set (tuples). Directions can be represented by an array of dx/dy and a direction index. Constraints (commands length up to 1e4, each move up to 9 steps) make per-step simulation acceptable. |
| 6 | +First thought: this is a straight simulation. Keep track of (x, y) and a facing direction. For each forward command, move one step at a time and check if the next cell is an obstacle. Use a set for obstacles (O(1) membership). Directions can be represented by a list of (dx, dy) vectors in a fixed order (e.g. north, east, south, west), and turning changes the index. |
7 | 7 |
|
8 | | -Edge-case: obstacle at (0,0) — important: robot starts at (0,0) and should ignore an obstacle at origin until it leaves; but our simulation only checks obstacles when stepping into a cell, so starting on (0,0) is fine and later attempts to re-enter (0,0) will be blocked normally. |
| 8 | +Edge details: obstacles can include (0,0) — that's fine since we don't check the starting cell for blocking; only stepping into a cell is blocked. Complexity will be dominated by the total number of single-step moves (sum of all movement commands), which is bounded by 9 * commands.length in worst case (<= 9e4 here), so simulation is efficient. |
9 | 9 |
|
10 | 10 | ## Refining the problem, round 2 thoughts |
11 | | -- Represent directions in order [north, east, south, west] with dx,dy arrays and update the direction index on turns: |
12 | | - - -2 (left): dir = (dir + 3) % 4 |
13 | | - - -1 (right): dir = (dir + 1) % 4 |
14 | | -- Convert obstacles to a set of tuples for O(1) containment checks. |
15 | | -- For each forward command k, do k single-step moves; if the cell ahead is an obstacle, stop processing this movement command and proceed to the next command. |
16 | | -- Keep track of max(x*x + y*y) after each successful step. |
17 | | -- Complexity: commands length up to 1e4 and each command moves at most 9 steps -> at most ~9e4 steps; obstacles up to 1e4. Using a set for obstacles yields efficient membership checks. |
18 | | -- Alternative approaches (e.g., precomputing nearest obstacle in each direction) are unnecessary here because forward steps are small; the simple simulation is clear and efficient for constraints. |
19 | | -- Make sure to handle negative coordinates correctly when storing obstacles (use tuple of ints). |
| 11 | +- Representation: obstacles as a set of tuples (x,y) is simple and fast. |
| 12 | +- Direction handling: let dirs = [(0,1),(1,0),(0,-1),(-1,0)] with index 0 = north. For -2 (turn left) we do dir = (dir + 3) % 4; for -1 (turn right) dir = (dir + 1) % 4. That mapping is concise and correct. |
| 13 | +- Movement: for a forward k, loop i in range(k) and attempt to step to (x+dx, y+dy); if that coordinate is in obstacles, break; else update position and update max distance squared. |
| 14 | +- Edge cases: obstacles empty; obstacle at origin handled naturally since we never check starting position; coordinates can be negative, storing tuples handles that fine. |
| 15 | +- Complexity: time O(C + S) where C = len(commands) and S = total single-step moves (S <= 9 * C). Space O(M) for obstacles set where M = len(obstacles). |
| 16 | + |
| 17 | +This approach is straightforward and optimal for given constraints. |
20 | 18 |
|
21 | 19 | ## Attempted solution(s) |
22 | 20 | ```python |
23 | | -from typing import List |
| 21 | +from typing import List, Set, Tuple |
24 | 22 |
|
25 | 23 | class Solution: |
26 | 24 | def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int: |
27 | | - # Convert obstacles to a set of tuples for O(1) lookup |
28 | | - obs = set(map(tuple, obstacles)) |
29 | | - |
30 | 25 | # Directions: north, east, south, west |
31 | 26 | dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] |
32 | | - d = 0 # start facing north |
| 27 | + d = 0 # start facing north (index 0) |
33 | 28 | x = y = 0 |
34 | 29 | max_dist_sq = 0 |
35 | | - |
| 30 | + |
| 31 | + # Convert obstacle list to a set of tuples for O(1) lookup |
| 32 | + obs_set: Set[Tuple[int, int]] = {(ox, oy) for ox, oy in obstacles} |
| 33 | + |
36 | 34 | for cmd in commands: |
37 | 35 | if cmd == -2: # turn left 90 degrees |
38 | 36 | d = (d + 3) % 4 |
39 | 37 | elif cmd == -1: # turn right 90 degrees |
40 | 38 | d = (d + 1) % 4 |
41 | 39 | else: |
42 | 40 | dx, dy = dirs[d] |
| 41 | + # move step by step |
43 | 42 | for _ in range(cmd): |
44 | 43 | nx, ny = x + dx, y + dy |
45 | | - if (nx, ny) in obs: |
46 | | - # obstacle blocks further movement for this command |
| 44 | + if (nx, ny) in obs_set: |
| 45 | + # blocked by obstacle, stop this command |
47 | 46 | break |
48 | 47 | x, y = nx, ny |
49 | | - dist_sq = x * x + y * y |
| 48 | + dist_sq = x*x + y*y |
50 | 49 | if dist_sq > max_dist_sq: |
51 | 50 | max_dist_sq = dist_sq |
52 | | - |
| 51 | + |
53 | 52 | return max_dist_sq |
54 | 53 | ``` |
55 | | -- Notes: |
56 | | - - Approach: Straightforward simulation. Use a set of obstacle coordinates for constant-time checks, maintain direction index and position, and step one unit at a time for move commands. |
57 | | - - Time complexity: O(C + S) where C is number of commands and S is total unit steps executed. Given each command moves at most 9 steps, S <= 9 * C, so effectively O(C + |obstacles|) for preprocessing the obstacle set. With constraints this is efficient. |
58 | | - - Space complexity: O(|obstacles|) for the obstacle set. |
59 | | - - Implementation detail: Using tuple coordinates (x,y) in a Python set handles negative coordinates and large ranges correctly. The special-case note about an obstacle at (0,0) is naturally handled because we only check obstacles when stepping into cells, not for the starting cell. |
| 54 | +- Notes on the solution: |
| 55 | + - Approach: simulate the robot step-by-step, using a set for obstacles to check each candidate cell in O(1). |
| 56 | + - Correctness: handles turning and single-step movement, and respects obstacle blocking semantics (stops only the current command's movement when an obstacle is encountered). |
| 57 | + - Time complexity: O(C + S) where C = len(commands) and S = sum of forward steps (S <= 9 * C). Given constraints this is efficient. |
| 58 | + - Space complexity: O(M) to store obstacles (M = len(obstacles)). |
0 commit comments