There is an intersection of two roads. First road is running from north to south in a straight line (i.e. north-south road). Second road is running from west to east in a straight line (i.e. west-east road).
These two roads intersect at a single point where traffic is controlled by a traffic light system.
There are two different threads modeling cars in each road. Each thread tries to increase the number of cars passing through the intersection.
Write a simulation of a traffic light controlled intersection using three functions:
carArrived(carId, roadId, direction, acquireGreen, releaseGreen)
:
carId
.roadId
.roadId
= 1 means north-south road.roadId
= 2 means west-east road.direction
with possible values:
NORTH
SOUTH
WEST
EAST
acquireGreen
is a function you should call to acquire access to the intersection.releaseGreen
is a function you should call to release access to the intersection.
isGreen()
: Returns true if the current traffic light is green on car's roadId
, otherwise returns false.
turnGreen()
: Turns the traffic light to green on the roadId
.Example 1:
Input: cars = [1,3,5,2,4], directions = ["NORTH","WEST","SOUTH","EAST","NORTH"], roads = [1,2,1,2,1] Output: ["NORTH","WEST","SOUTH","EAST","NORTH"]
Explanation:
The simulation follows these steps:
Example 2:
Input: cars = [1,2,3,4,5], directions = ["NORTH","EAST","WEST","SOUTH","NORTH"], roads = [1,2,2,1,1] Output: ["NORTH","EAST","WEST","SOUTH","NORTH"]
Constraints:
1 <= cars.length <= 20
cars.length = directions.length
cars.length = roads.length
1 <= carId <= 20
roadId
is one of the two possible values: {1,2}
direction
is one of the four possible values: {"NORTH","SOUTH","EAST","WEST"}
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:
The brute force approach to managing traffic lights at an intersection involves checking every possible combination of light timings. We'll explore all scenarios, from very short green light durations to very long ones, to see which timing configuration minimizes waiting vehicles. This means literally trying every possible green light duration combination for the different directions and seeing which one works best.
Here's how the algorithm would work step-by-step:
def traffic_light_brute_force(roads, max_green_time): best_timing = None
min_waiting_cars = float('inf')
# Iterate through all possible green light durations for each road
for green_time_road_one in range(1, max_green_time + 1):
for green_time_road_two in range(1, max_green_time + 1):
for green_time_road_three in range(1, max_green_time + 1):
for green_time_road_four in range(1, max_green_time + 1):
green_light_durations = [
green_time_road_one,
green_time_road_two,
green_time_road_three,
green_time_road_four,
]
total_waiting_cars = 0
# Simulate traffic flow for the current light durations
for road_index, road in enumerate(roads):
waiting_cars = road['arrival_rate'] * (sum(green_light_durations) - green_light_durations[road_index])
total_waiting_cars += waiting_cars
# Check if this combination results in fewer waiting cars
if total_waiting_cars < min_waiting_cars:
min_waiting_cars = total_waiting_cars
best_timing = green_light_durations
# Return the best timing found
return best_timing
The key to efficiently managing traffic flow at an intersection is to grant access to roads in a way that minimizes overall waiting time. The system should change lights based on the perceived need, prioritizing fairness and preventing starvation for any single direction.
Here's how the algorithm would work step-by-step:
class TrafficLightControlledIntersection:
def __init__(self, directions):
self.directions = directions
self.waiting_vehicles = {direction: 0 for direction in directions}
self.current_green_direction = None
self.green_light_duration = 10
self.yellow_light_duration = 3
self.time = 0
def update_waiting_vehicles(self, direction, number_of_vehicles):
self.waiting_vehicles[direction] += number_of_vehicles
def choose_next_direction(self):
# Prioritize directions with the most waiting vehicles
best_direction = None
max_waiting_vehicles = -1
for direction, vehicles in self.waiting_vehicles.items():
if vehicles > max_waiting_vehicles and direction != self.current_green_direction:
max_waiting_vehicles = vehicles
best_direction = direction
if best_direction is None:
#If all directions have 0 vehicles, cycle to the next one.
directions_list = list(self.directions)
if self.current_green_direction is None:
return directions_list[0]
current_index = directions_list.index(self.current_green_direction)
next_index = (current_index + 1) % len(directions_list)
return directions_list[next_index]
return best_direction
def handle_emergency_vehicle(self, emergency_direction):
#Immediately give right-of-way to emergency vehicles
self.set_light(emergency_direction)
def set_light(self, direction):
print(f"Time: {self.time} - Setting light to GREEN for {direction}")
self.current_green_direction = direction
self.waiting_vehicles[direction] = 0
self.time += self.green_light_duration
print(f"Time: {self.time} - Setting light to YELLOW for {direction}")
self.time += self.yellow_light_duration
print(f"Time: {self.time} - Setting light to RED for {direction}")
def run_simulation(self, duration):
while self.time < duration:
next_direction = self.choose_next_direction()
# Only change the light if there is a valid next direction.
if next_direction:
self.set_light(next_direction)
else:
self.time += 1
if __name__ == '__main__':
intersection = TrafficLightControlledIntersection(['North', 'South', 'East', 'West'])
# Simulate vehicle arrivals
intersection.update_waiting_vehicles('North', 5)
intersection.update_waiting_vehicles('South', 2)
intersection.update_waiting_vehicles('East', 8)
intersection.update_waiting_vehicles('West', 1)
# Run the simulation for 60 seconds
intersection.run_simulation(60)
Case | How to Handle |
---|---|
No cars approaching the intersection from any direction | The traffic lights should remain in their default state, perhaps alternating green periodically to prevent indefinite waits on other directions. |
Cars approaching from all directions simultaneously | The algorithm must prioritize or use a predefined order to handle simultaneous requests to ensure fairness and prevent starvation. |
One direction has a continuous stream of cars while others have none | Implement a maximum green light duration to prevent one direction from monopolizing the intersection and starving other directions. |
A car arrives right as the light turns red for its direction | The algorithm should have a grace period or minimum red duration to prevent constant switching if a car arrives immediately after the light changes. |
Integer overflow when calculating wait times or durations | Use appropriate data types (e.g., long) to prevent overflow or implement checks to handle potential overflows gracefully. |
Emergency vehicle approaching the intersection | The system should have a mechanism to immediately switch the lights to allow the emergency vehicle to pass safely, potentially interrupting normal cycling. |
Malfunctioning sensor reporting incorrect car counts | Implement sanity checks and fallback mechanisms (e.g., using historical data or fixed timings) to handle unreliable sensor data. |
System receives conflicting signals from multiple sensors | Implement a conflict resolution strategy, such as prioritizing data from more reliable sensors or using a weighted average of sensor readings. |