#!/usr/bin/python # -*- coding: utf-8 -*- """See calendarprob.py. This version is, I think, correct, and only 22 lines of code rather than 34 lines. It took me 13 minutes to write, because it was buggy at first, while the version in calendarprob.py (more straightforward in my view) only took 11. But this version is, I think, correct in handling meetings that cross day boundaries. Also, it handles meetings for any number of people. I feel like this might be simpler with numpy argsort... """ def intervals(persons): n = 0 for t, d in sorted(item for meetings, (start, end) in persons for item in [(a, -1) for a, b in meetings] + [(b, +1) for a, b in meetings] + [(start, +1), (end, -1)]): n += d # number of people available from this time yield t, n def allopen(persons, duration): times = list(intervals(persons)) for i, (t, n) in enumerate(times[:-1]): u = times[i+1][0] if n == len(persons) and midminutes(u) - midminutes(t) >= duration: yield t, u def midminutes(t): return t // 100 * 60 + t % 100 if __name__ == '__main__': persons = [ ([(900, 1030), (1200, 1300), (1600, 1800)], (900, 2000)), ([(1000, 1130), (1230, 1430), (1430, 1500), (1600, 1700)], (1000, 1830)), ] #print(list(intervals(persons))) print(list(allopen(persons, 30)))