Code challenge: Can the guards of the stadium guard all gates
Question:
I am looking at this code challenge:
There are 26 Gates enumerated with the uppercase English alphabet from A to Z. The door of each gate is opened right before the first person enters and closed right after the arrival of the last guest that should enter through this gate. No two guests can enter the stadium simultaneously. For a gate to be properly checked, a security guard should be assigned to it. There are ‘k’ such guards in the stadium, so if there are more than ‘k’ gates opened, one of them is going to be left unguarded. Note that a guard can’t leave his post until the gate he is guarding is closed. Can we check if there was a moment when more than ‘k’ doors were opened? From the barcode scanning, we know the order in which the people having tickets entered.
Input:
- No of people = 5
- No of guards (k) = 1
- Gate used by ith guest: AABBB
Output: NO
Input:
- No of people = 5
- No of guards (k) = 1
- Gate used by ith guest: ABABB
Output: YES
I tried using deque to store the incoming alphabet is different from the previous alphabet and pop until the same alphabet is repeated. Not giving desired output. This is the code I tried:
from collections import deque
def solve(people, k, gate):
stack = deque() # Stack to track opened gates
counter = 0 # Counter for opened gates
for gate in gate_usage:
if len(stack) == 0 or stack[-1] == gate:
stack.append(gate)
else:
while len(stack) > 0 and stack[-1] != gate:
stack.pop()
counter += 1
if counter > k:
return "NO"
return "YES"
no_of_people = 5
k = 1
gate_usage = "ABABB"
print(solve(no_of_people, k, gate_usage))
Answers:
A solution is to gather for each gate which is its first use and its last use (the index in the input string is the time dimension). Then iterate the time points in order and when that time has a first use of a gate, decrease (the available guards), and when that time has a last use of a gate, increase . If ever becomes negative we have an overrun and should return "YES".
Implementation:
def solve(k, gate_usage):
last = { gate: time
for time, gate in enumerate(gate_usage)
}
first = { gate: time
for time, gate in reversed(list(enumerate(gate_usage)))
}
for time, gate in enumerate(gate_usage):
if time == first[gate]:
k -= 1
if k < 0:
return "YES"
if time == last[gate]:
k += 1
return "NO"
# Example runs
print(solve(2, "EAEBACDBDB")) # NO
print(solve(2, "EAEBADCBDB")) # YES
I am looking at this code challenge:
There are 26 Gates enumerated with the uppercase English alphabet from A to Z. The door of each gate is opened right before the first person enters and closed right after the arrival of the last guest that should enter through this gate. No two guests can enter the stadium simultaneously. For a gate to be properly checked, a security guard should be assigned to it. There are ‘k’ such guards in the stadium, so if there are more than ‘k’ gates opened, one of them is going to be left unguarded. Note that a guard can’t leave his post until the gate he is guarding is closed. Can we check if there was a moment when more than ‘k’ doors were opened? From the barcode scanning, we know the order in which the people having tickets entered.
Input:
- No of people = 5
- No of guards (k) = 1
- Gate used by ith guest: AABBB
Output: NO
Input:
- No of people = 5
- No of guards (k) = 1
- Gate used by ith guest: ABABB
Output: YES
I tried using deque to store the incoming alphabet is different from the previous alphabet and pop until the same alphabet is repeated. Not giving desired output. This is the code I tried:
from collections import deque
def solve(people, k, gate):
stack = deque() # Stack to track opened gates
counter = 0 # Counter for opened gates
for gate in gate_usage:
if len(stack) == 0 or stack[-1] == gate:
stack.append(gate)
else:
while len(stack) > 0 and stack[-1] != gate:
stack.pop()
counter += 1
if counter > k:
return "NO"
return "YES"
no_of_people = 5
k = 1
gate_usage = "ABABB"
print(solve(no_of_people, k, gate_usage))
A solution is to gather for each gate which is its first use and its last use (the index in the input string is the time dimension). Then iterate the time points in order and when that time has a first use of a gate, decrease (the available guards), and when that time has a last use of a gate, increase . If ever becomes negative we have an overrun and should return "YES".
Implementation:
def solve(k, gate_usage):
last = { gate: time
for time, gate in enumerate(gate_usage)
}
first = { gate: time
for time, gate in reversed(list(enumerate(gate_usage)))
}
for time, gate in enumerate(gate_usage):
if time == first[gate]:
k -= 1
if k < 0:
return "YES"
if time == last[gate]:
k += 1
return "NO"
# Example runs
print(solve(2, "EAEBACDBDB")) # NO
print(solve(2, "EAEBADCBDB")) # YES