I need to implement an algorithm for my managing application that will tell me when and to which user a task can be assigned.
I implemented a brute force solution, it seems to work, but I'd like to know if there is more efficient way to do this. For sake of simplicity I've rewritten the algorithm to operate on lists of numbers(instead of db queries and such). Below i will try to explain my way of thinking.
Let's say we have 3 users that can be potentially assigned to the task.
user_a_busy = [[1,2], [2,4], [5,6]]
user_b_busy = [[4,7], [7,8]]
user_c_busy = [[0,1], [1,5]]
Each element of the list represents a period in which user is not available during the day. So User A is busy between 1 AM and 2 AM, 2 AM and 4 AM and so on. To make it possible to iterate over users and identify them i represent the above lists in form of dictionary.
users_to_check = {'A':user_a_busy, 'B':user_b_busy, 'C':user_c_busy}
Now let's say we have a task that takes 1 hour to complete and we want to check a period between midnight and 10 AM in 1 hour intervals(so tasks can start only on whole hours). Here is a representation of every period to check in form of a list.
task_intervals_to_check = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10]]
Here is a function that checks if two intervals overlap:
def intervals_overlap(service, busy):
if service[1] > busy[0] and service[0] < busy[1]:
return True
return False
So now here is the loop that results in dictionary of available hours and users that can be assigned to the task:
result = defaultdict(list)
for interval in task_intervals_to_check:
for user, user_busy in users_to_check.iteritems():
overlaps = False
for busy_period in user_busy:
if intervals_overlap(interval, busy_period):
overlaps = True
break
if not overlaps:
result[interval[0]].append(user)
For task of length of 1 hour the result is:
{0: ['A', 'B'], 1: ['B'], 2: ['B'], 3: ['B'], 4: ['A'], 5: ['C'], 6: ['A', 'C'], 7: ['A', 'C'], 8: ['A', 'C', 'B'], 9: ['A', 'C', 'B']}
For task of length of 2 hours the result is:
{0: ['B'], 1: ['B'], 2: ['B'], 5: ['C'], 6: ['A', 'C'], 7: ['A', 'C'], 8: ['A', 'C', 'B']}
Which is an expected result. Below is the diagram which helped me to find correct results:
So now my question is, is there any way to optimise this solution? Is this an acceptable solution?