Taro Logo

Robot Bounded In Circle

Medium
Amazon logo
Amazon
1 view
Topics:
ArraysStrings

On an infinite plane, a robot initially stands at (0, 0) and faces north. The robot can receive one of three instructions:

  1. "G": go straight 1 unit.
  2. "L": turn 90 degrees to the left (anti-clockwise direction).
  3. "R": turn 90 degrees to the right (clockwise direction).

The robot performs the instructions given in order and repeats them forever.

Return true if and only if there exists a circle in the plane such that the robot never leaves the circle.

For example, given the instructions "GGLLGG", the output should be true because the robot returns to the origin after a cycle. Given the instructions "GG", the output should be false because the robot moves indefinitely in the north direction. Given the instructions "GL", the output should be true because the robot moves in a circular pattern and returns to the origin after four cycles.

Solution


Clarifying Questions

When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:

  1. What is the maximum length of the instruction string? Can it be empty?
  2. Are the only instructions allowed 'G', 'L', and 'R', or could there be other characters in the input string?
  3. Does 'G' always move the robot one unit forward?
  4. If the robot returns to the origin, but is not facing North, is that still considered bounded?
  5. Should I assume the initial position of the robot is (0, 0) facing North?

Brute Force Solution

Approach

Imagine physically walking a robot around a grid following instructions. A brute force approach means we'd literally repeat the given instructions many, many times and see where the robot ends up.

Here's how the algorithm would work step-by-step:

  1. Start the robot at its initial position, facing a certain direction (like North).
  2. Follow the instruction sequence exactly once, which might involve moving forward or changing direction.
  3. Record the robot's new position and the direction it's facing.
  4. Repeat the instruction sequence a large number of times, each time starting from the robot's last recorded position and direction.
  5. After all those repetitions, check where the robot is located.
  6. If the robot is back at its starting position, no matter which direction it's facing, then it's bounded in a circle.
  7. If the robot is not at its starting position but it's facing the same direction it started with, then it will continue to go further and further away and is not bounded.
  8. If the robot is not at its starting position, but it's facing a different direction, it still might be going in a circle. So check that possibility.
  9. If after all the repetitions, the robot is not back at the origin, assume it's not bounded.

Code Implementation

def is_robot_bounded(instructions):    initial_x_coordinate = 0
    initial_y_coordinate = 0
    current_direction = 'North'
    number_of_repetitions = 4

    for _ in range(number_of_repetitions):
        for instruction in instructions:
            if instruction == 'G':
                if current_direction == 'North':
                    initial_y_coordinate += 1
                elif current_direction == 'South':
                    initial_y_coordinate -= 1
                elif current_direction == 'East':
                    initial_x_coordinate += 1
                else:
                    initial_x_coordinate -= 1
            elif instruction == 'L':
                # Changing direction counter-clockwise
                if current_direction == 'North':
                    current_direction = 'West'

                elif current_direction == 'West':
                    current_direction = 'South'

                elif current_direction == 'South':
                    current_direction = 'East'

                else:
                    current_direction = 'North'

            else:
                # Changing direction clockwise
                if current_direction == 'North':
                    current_direction = 'East'

                elif current_direction == 'East':
                    current_direction = 'South'

                elif current_direction == 'South':
                    current_direction = 'West'

                else:
                    current_direction = 'North'

    # Robot returns to origin after repetitions
    if initial_x_coordinate == 0 and initial_y_coordinate == 0:
        return True

    # If robot direction changed it is bounded
    if current_direction != 'North':
        return True

    return False

Big(O) Analysis

Time Complexity
O(n)The algorithm simulates the robot's movements based on a sequence of instructions. The key operation is repeating the instruction sequence. The complexity is driven by the number of times we repeat the instruction sequence, which we can treat as a constant, say k. If the instruction sequence length is n, the total number of operations is k * n. Since k is a constant factor (likely a small integer), we can ignore it in Big O notation. Therefore, the time complexity simplifies to O(n).
Space Complexity
O(1)The provided plain English explanation describes a process where the robot's position and direction are updated iteratively. It doesn't mention storing intermediate positions, visited locations, or gathering items in any data structure. The algorithm only needs to keep track of the current position (x, y coordinates) and the direction, which are constant number of variables. Thus, the space used is constant and independent of the input size N (the instruction sequence length). Therefore, the space complexity is O(1).

Optimal Solution

Approach

The key idea is that if the robot returns to its starting point OR faces the same direction it started in, it's bounded in a circle. We simulate the robot's moves and only need to track its position and direction after one full set of instructions.

Here's how the algorithm would work step-by-step:

  1. Imagine the robot starts at a specific point, facing North.
  2. Follow the instructions one by one, updating the robot's position and the direction it's facing.
  3. If the instruction is 'G', move the robot one step forward in the direction it's facing.
  4. If the instruction is 'L', turn the robot 90 degrees to the left.
  5. If the instruction is 'R', turn the robot 90 degrees to the right.
  6. After following all instructions once, check two things: has the robot returned to its original starting point? OR, is the robot facing a different direction than it started in?
  7. If either of those conditions are true, then the robot will eventually be trapped in a circle.

Code Implementation

def is_robot_bounded(instructions: str) -> bool:
    current_direction = 0
    current_x_position = 0
    current_y_position = 0
    directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]

    for instruction in instructions:
        if instruction == 'G':
            current_x_position += directions[current_direction][0]
            current_y_position += directions[current_direction][1]
        elif instruction == 'L':
            # Turning left means decrementing direction index.
            current_direction = (current_direction - 1) % 4

        elif instruction == 'R':
            # Turning right means incrementing direction index.
            current_direction = (current_direction + 1) % 4

    # Check if the robot returned to the origin or faces a different direction
    if (current_x_position == 0 and current_y_position == 0) or current_direction != 0:
        return True
    else:
        return False

Big(O) Analysis

Time Complexity
O(n)The algorithm iterates through the instructions string once. The number of instructions is represented by n, which denotes the length of the input string. Inside the loop, each instruction 'G', 'L', or 'R' takes constant time to process, updating the robot's position or direction. Therefore, the time complexity is directly proportional to the number of instructions n, resulting in a linear time complexity. The total operations approximate to n, thus the Big O is O(n).
Space Complexity
O(1)The algorithm's space complexity is O(1) because it uses a fixed number of variables to store the robot's current position (x, y) and direction. The number of instructions, N, in the input string does not affect the amount of extra memory used; the algorithm only updates these fixed-size variables as it iterates through the instructions. Therefore, no auxiliary data structures that scale with the input size are used, resulting in constant auxiliary space.

Edge Cases

CaseHow to Handle
Empty instruction stringThe robot doesn't move, so the end location is (0, 0) and direction is North, thus bounded.
String contains only 'G' instructionsThe robot moves in one direction indefinitely and is not bounded.
String contains only 'L' or 'R' instructionsThe robot rotates without moving, resulting in a bounded circle.
String with very long sequence of instructions.The solution should handle long instruction strings efficiently, likely with modular arithmetic to track direction.
Integer overflow in coordinate calculations (very long 'G' sequence).Use long or appropriate data type to avoid overflow when accumulating coordinates.
Instructions perfectly cancel each other out (e.g., 'GLGLGLGL')The robot ends up at the origin, and therefore it is bounded.
Single rotation instruction ('L' or 'R').The robot rotates and stays at the origin (0,0), which means it is bounded.
String with non 'G', 'L', 'R' characterThe solution should throw an exception or handle it gracefully, for example by ignoring the unexpected characters.