Last active
January 1, 2025 14:33
-
-
Save NikitaShkaruba/c5068a602a0d7993a8488e8e6cd695ca to your computer and use it in GitHub Desktop.
A scheduler class that your favorite calendar uses to quickly find a meeting room (I was tasked to write it while interviewing at Uber)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sortedcontainers import SortedList | |
from collections import dict | |
class Interval: | |
def __init__(self, start: int, end: int): | |
self.start = start | |
self.end = end | |
def __repr__(self): | |
return str(self) | |
def __str__(self): | |
return '(' + str(self.start) + ',' + str(self.end) + ')' | |
class Room: | |
def __init__(self, name: str): | |
self.name = name | |
self.meetings = SortedList([], key = lambda x: x.start) | |
class Scheduler: | |
def __init__(self, roomNames: List[str]): | |
self.rooms = [Room(name) for name in roomNames] | |
self.roomMap = dict((name, idx) for idx, name in enumerate(roomNames)) | |
def findRoom(self, meetingTime: Interval) -> str: | |
''' | |
Works in O(r*log(m)) time | |
- Where r is the amount of rooms, and m is the max amount of meetings in the room | |
''' | |
for room in self.rooms: | |
i = room.meetings.bisect_left(meetingTime) | |
if i < len(room.meetings) and room.meetings[i].start < meetingTime.end: | |
continue | |
if i-1 >= 0 and room.meetings[i-1].end > meetingTime.start: | |
continue | |
room.meetings.add(meetingTime) | |
return room.name | |
raise Exception('no rooms available for meeting ' + str(meetingTime)) | |
def listIntervals(self, roomName: str) -> List[Interval]: | |
''' | |
Works in O(m) time | |
- Where m is the amount of meetings in the room | |
''' | |
if roomName not in self.roomMap: | |
raise Exception('no rooms available') | |
roomIdx = self.roomMap[roomName] | |
return [x for x in self.rooms[roomIdx].meetings] | |
def printSchedulerIntervals(scheduler: Scheduler, roomNames: List[str]) -> None: | |
print('Rooms schedule:') | |
for name in roomNames: | |
print(name, scheduler.listIntervals(name)) | |
print() | |
roomNames = ['Airport', 'Carwash', 'Theater'] | |
scheduler = Scheduler(roomNames) | |
scheduler.findRoom(Interval(3,4)) | |
scheduler.findRoom(Interval(0,2)) | |
scheduler.findRoom(Interval(2,3)) | |
scheduler.findRoom(Interval(5,7)) | |
scheduler.findRoom(Interval(10,15)) | |
printSchedulerIntervals(scheduler, roomNames) | |
scheduler.findRoom(Interval(3,4)) | |
scheduler.findRoom(Interval(5,6)) | |
scheduler.findRoom(Interval(6,9)) | |
scheduler.findRoom(Interval(0,1)) | |
scheduler.findRoom(Interval(11,12)) | |
printSchedulerIntervals(scheduler, roomNames) | |
scheduler.findRoom(Interval(0,16)) | |
printSchedulerIntervals(scheduler, roomNames) | |
badIntervals = [ | |
Interval(0,16), | |
Interval(0,5), | |
Interval(11,17), | |
Interval(5,6), | |
] | |
for badInterval in badIntervals: | |
try: | |
scheduler.findRoom(badInterval) | |
except Exception as err: | |
print('Caught an error:', err) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output