Robot Collisions

Updated on 20 June, 2025
Robot Collisions header image

Problem Statement

In this problem, we are dealing with a simulation where multiple robots, each uniquely placed on a straight line with individual properties of position, health, and direction of movement, start to move simultaneously. The robots can only move left ('L') or right ('R'). Throughout their movement, if any two robots occupy the same position at the same time, a collision occurs. The outcome of each collision is dependent on the health of the participating robots:

  • If one robot has higher health than the other, the weaker robot is removed from the line and the health of the stronger one decreases by 1.
  • If both robots have equal health, both are removed from the scene.

The goal is to compute the health values of any robots that survive after all possible collisions have been resolved. The results should be presented in the order of the original input list of robots. Moreover, if no robots survive, an empty array should be returned.

Examples

Example 1

Input:

positions = [5,4,3,2,1], healths = [2,17,9,15,10], directions = "RRRRR"

Output:

[2,17,9,15,10]

Explanation:

No collision occurs in this example, since all robots are moving in the same direction. So, the health of the robots in order from the first robot is returned, [2, 17, 9, 15, 10].

Example 2

Input:

positions = [3,5,2,6], healths = [10,10,15,12], directions = "RLRL"

Output:

[14]

Explanation:

There are 2 collisions in this example. Firstly, robot 1 and robot 2 will collide, and since both have the same health, they will be removed from the line. Next, robot 3 and robot 4 will collide and since robot 4's health is smaller, it gets removed, and robot 3's health becomes 15 - 1 = 14. Only robot 3 remains, so we return [14].

Example 3

Input:

positions = [1,2,5,6], healths = [10,10,11,11], directions = "RLRL"

Output:

[]

Explanation:

Robot 1 and robot 2 will collide and since both have the same health, they are both removed. Robot 3 and 4 will collide and since both have the same health, they are both removed. So, we return an empty array, [].

Constraints

  • 1 <= positions.length == healths.length == directions.length == n <= 105
  • 1 <= positions[i], healths[i] <= 109
  • directions[i] == 'L' or directions[i] == 'R'
  • All values in positions are distinct

Approach and Intuition

Given the complexity of the robot interactions, here's a clarifying approach that breaks down how collisions can be resolved efficiently.

  • Sorting Robots by Position: To simplify the processing of movements and collisions, we first sort the robots based on their positions. This aids in determining which robots will meet and potentially collide as they move.

  • Processing Movements and Collisions: Essentially, we only need to be concerned about pairs of robots where one is moving towards the other. This is particularly relevant for pairs where one robot has 'R' in the directions and the adjacent one has 'L'. Other configurations either don't result in a collision, or they always pass through without meeting (both moving in the same direction). From the examples:

    • In Example 1, all robots move to the right, making it impossible for any collisions to occur.
    • Example 2 and Example 3 highlight situations where we have alternating directions, leading to potential or actual collisions.
  • Handling Collisions: For each encounter between two robots moving towards each other:

    • Calculate the meeting point and check the health to decide the outcome (robot survives, both robots get removed, etc.).
    • Update the health and, if necessary, remove the affected robots from further consideration.
  • Edge Cases: Handle scenarios with an uneven distribution of movement directions or where all robots move in a single direction, as these either limit or completely negate the possibility of a collision.

By organizing the robots based on positions and then scrutinizing potential collisions based on direction and health, it becomes manageable to simulate the entire process efficiently, adhering to the given constraints.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    vector<int> remainingRobotsHealth(vector<int>& coords, vector<int>& vitality, string movement) {
        int total = coords.size();
        vector<int> sortingIndex(total), survivors;
        stack<int> robots;

        for (int i = 0; i < total; ++i) {
            sortingIndex[i] = i;
        }

        sort(sortingIndex.begin(), sortingIndex.end(),
             [&](int left, int right) { return coords[left] < coords[right]; });

        for (int sortedIdx : sortingIndex) {
            if (movement[sortedIdx] == 'R') {
                robots.push(sortedIdx);
            } else {
                while (!robots.empty() && vitality[sortedIdx] > 0) {
                    int encounterIdx = robots.top();
                    robots.pop();
                    
                    if (vitality[encounterIdx] > vitality[sortedIdx]) {
                        vitality[encounterIdx] -= 1;
                        vitality[sortedIdx] = 0;
                        robots.push(encounterIdx);
                    } else if (vitality[encounterIdx] < vitality[sortedIdx]) {
                        vitality[sortedIdx] -= 1;
                        vitality[encounterIdx] = 0;
                    } else {
                        vitality[sortedIdx] = 0;
                        vitality[encounterIdx] = 0;
                    }
                }
            }
        }

        // Gather robots that are still in good condition
        for (int idx = 0; idx < total; ++idx) {
            if (vitality[idx] > 0) {
                survivors.push_back(vitality[idx]);
            }
        }
        return survivors;
    }
};

In the provided C++ solution, the task is to determine the remaining health of robots after a series of movements and collisions. Robots that face right (R) and left (L) collide based on their positions and health points. The solution employs sorting to track the positions of robots and simulate the collisions using conditions derived from their health points and directions.

Here's a breakdown of how the solution tackles this problem:

  • Initialization: Arrays for coords (positions of the robots) and vitality (health points) are taken as input along with a movement string. Auxiliary containers, like sortingIndex for tracking sorted indices of coords, and a stack for robots facing right, are initialized.

  • Sorting: Robots are sorted by their positions using a custom comparator. This ensures that processing happens from the leftmost robot to the rightmost, aiding in the simulation of movements and collisions accurately.

  • Collision Simulation: Iterations take place in the order of sorted positions. If a robot faces right, its index is pushed onto the stack. When encountering a robot facing left, collisions are checked with any robot facing right (detected by examining the stack):

    • If vitality of the robot from the stack (facing right) is greater than the current left-facing robot, the right-facing robot decreases its vital by 1, and the left-facing robot's vitality drops to 0, indicating it's out.
    • If the left-facing robot has higher vital, vice versa occurs.
    • If both have equal vitality, both are set to 0.
  • Determine Survivors: After processing all robots, the vector survivors is filled with the vitalities of robots that still maintain a vitality greater than 0.

This method ensures efficiency by avoiding direct O(n^2) comparisons and leverages sorting and stack operations to handle collisions in an optimal way relative to the sequence of robot positions and movements.

java
class Solution {

    public List<Integer> remainingRobotsHealth(
        int[] placements,
        int[] vitality,
        String movements
    ) {
        int count = placements.length;
        Integer[] sortedIndices = new Integer[count];
        List<Integer> survivors = new ArrayList<>();
        Stack<Integer> collisionStack = new Stack<>();

        for (int i = 0; i < count; ++i) {
            sortedIndices[i] = i;
        }

        Arrays.sort(
            sortedIndices,
            (left, right) -> Integer.compare(placements[left], placements[right])
        );

        for (int sortedIndex : sortedIndices) {
            if (movements.charAt(sortedIndex) == 'R') {
                collisionStack.push(sortedIndex);
            } else {
                while (!collisionStack.isEmpty() && vitality[sortedIndex] > 0) {
                    int stackTop = collisionStack.pop();

                    if (vitality[stackTop] > vitality[sortedIndex]) {
                        vitality[stackTop] -= 1;
                        vitality[sortedIndex] = 0;
                        collisionStack.push(stackTop);
                    } else if (vitality[stackTop] < vitality[sortedIndex]) {
                        vitality[sortedIndex] -= 1;
                        vitality[stackTop] = 0;
                    } else {
                        vitality[sortedIndex] = 0;
                        vitality[stackTop] = 0;
                    }
                }
            }
        }

        for (int idx = 0; idx < count; ++idx) {
            if (vitality[idx] > 0) {
                survivors.add(vitality[idx]);
            }
        }
        return survivors;
    }
}

The provided Java solution is designed to simulate a scenario where robots placed on a line and moving in specified directions can collide based on their movements. Each robot has a corresponding health level, and the output should be the remaining health of the robots that survive any collisions.

Explanation:

  • Robots and their properties are represented by two arrays placements and vitality, and their movement directions are indicated by a string movements.
  • Each robot is initially considered by sorting them based on their placement positions to process encounters sequentially.
  • A stack (collisionStack) is utilized to manage collisions in sequence. If a robot moves right ('R'), it is pushed onto the stack. Conversely, when a robot moving left is encountered, the stack is processed:
    1. Robots popping from the stack (moving right) collide with the current left-moving robot.
    2. The collision results in the decrement of their health based on the conditions given; if the health of colliding robots is equal, both are considered destroyed (health becomes zero). If one robot's health is greater, it survives, and the weaker robot's health becomes zero.
  • After processing all movements and collisions, the remaining health values are gathered for robots that have a non-zero health, indicating their survival.

Result:

  • The method remainingRobotsHealth returns a list of the health values for the surviving robots after all possible collisions have been resolved based on the initial positions, health, and movements of the robots using effective data structures like arrays, stacks, and sorting mechanisms for an efficient solution.
python
class Solution:
    def finalRobotsHealths(
        self, positions: List[int], healths: List[int], directions: str
    ) -> List[int]:
        count = len(positions)
        robot_indices = list(range(count))
        output = []
        collision_stack = deque()

        # Sorting based on robot positions
        robot_indices.sort(key=lambda idx: positions[idx])

        for idx in robot_indices:
            # Process right-moving robots
            if directions[idx] == "R":
                collision_stack.append(idx)
            else:
                while collision_stack and healths[idx] > 0:
                    # Resolving collisions
                    last_idx = collision_stack.pop()

                    if healths[last_idx] > healths[idx]:
                        # Last index robot wins the collision
                        healths[last_idx] -= 1
                        healths[idx] = 0
                        collision_stack.append(last_idx)
                    elif healths[last_idx] < healths[idx]:
                        # Current index robot wins the collision
                        healths[idx] -= 1
                        healths[last_idx] = 0
                    else:
                        # Both robots are destroyed
                        healths[idx] = 0
                        healths[last_idx] = 0

        # Remaining robots with non-zero health
        for index in range(count):
            if healths[index] > 0:
                output.append(healths[index])

        return output

This Python program calculates the final health of robots moving on a line after potential collisions. Each robot has a position, initial health, and a direction of movement, either right ("R") or left ("L"). Here's a concise breakdown of the implementation:

  • The program first retrieves the number of robots and initializes an output list and a stack to handle collisions.
  • The robots are sorted by their positions to ensure they are processed in the correct order of potential collisions.
  • The program uses a loop to assess each robot:
    • If a robot moves right, its index gets pushed onto the stack.
    • If a robot moves left, it triggers collision checks with any right-moving robots that were previously added to the stack.
  • Collisions are resolved based on their health:
    • If the right-moving robot has higher health, the left-moving robot is annihilated, and the right-moving robot loses one health unit but remains in the stack for further collision checks.
    • If the left-moving robot has higher health, it assumes the winner's position with decreased health, and the right-moving robot is annihilated.
    • If both have equal health, both robots are annihilated.
  • After processing all robots, the remaining robots' healths are compiled into the output list if their health is non-zero.

This logic ensures that only robots that survive collisions and still contain health are listed in the output, neatly capturing the dynamics of robot movements and interactions.

Comments

No comments yet.