Guest User

Untitled

a guest
Apr 25th, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.00 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. """
  3. :authors: python273
  4. :license: Apache License, Version 2.0
  5. :copyright: (c) 2018 python273
  6. """
  7. from itertools import chain
  8. from numbers import Number
  9.  
  10. from sortedcontainers import SortedList
  11.  
  12.  
  13. class Container:
  14. __slots__ = ('from_', 'to', 'obj')
  15.  
  16. def __init__(self, from_, to, obj=None):
  17. self.from_ = from_
  18. self.to = to
  19. self.obj = obj
  20.  
  21. def __eq__(self, other):
  22. if isinstance(other, Number):
  23. return self.from_ == other
  24.  
  25. return self.from_ == other.from_
  26.  
  27. def __lt__(self, other):
  28. if isinstance(other, Number):
  29. return self.from_ < other
  30.  
  31. return self.from_ < other.from_
  32.  
  33. def __gt__(self, other):
  34. if isinstance(other, Number):
  35. return self.from_ > other
  36.  
  37. return self.from_ > other.from_
  38.  
  39. def __repr__(self):
  40. return 'Container({}, {}, {})'.format(self.from_, self.to, self.obj)
  41.  
  42.  
  43. class Line:
  44. __slots__ = ('from_', 'to', 'l')
  45.  
  46. def __init__(self, from_, to):
  47. self.from_ = from_
  48. self.to = to
  49.  
  50. self.l = SortedList()
  51.  
  52. def can_mark(self, from_, to):
  53. included = (
  54. (self.from_ <= from_ < self.to) and
  55. (self.from_ <= to < self.to)
  56. )
  57. if not included:
  58. raise ValueError('Not included in interval')
  59.  
  60. existing_index = self.l.bisect(from_) - 1
  61.  
  62. if existing_index >= 0:
  63. existing = self.l[existing_index]
  64.  
  65. intersects = (
  66. (existing.from_ <= from_ < existing.to) or
  67. (existing.from_ <= to < existing.to)
  68. )
  69.  
  70. if intersects:
  71. return False
  72.  
  73. existing_index += 1
  74. if existing_index >= len(self.l):
  75. return True
  76.  
  77. existing = self.l[existing_index]
  78.  
  79. return to <= existing.from_
  80.  
  81. return True
  82.  
  83. def mark(self, from_, to, obj):
  84. if not self.can_mark(from_, to):
  85. raise ValueError('Already marked')
  86.  
  87. self.l.add(Container(from_, to, obj))
  88.  
  89. def __iter__(self):
  90. return iter(self.l)
  91.  
  92. def get(self, x):
  93. existing_index = self.l.bisect(x) - 1
  94.  
  95. if existing_index >= 0:
  96. existing = self.l[existing_index]
  97.  
  98. if x < existing.to:
  99. return existing
  100.  
  101. raise IndexError
  102.  
  103. def get_free(self):
  104. free_intervals = []
  105.  
  106. prev = None
  107.  
  108. for curr in chain(self.l, [None]):
  109. if prev is None:
  110. if curr.from_ > self.from_:
  111. free_intervals.append([self.from_, curr.from_])
  112. elif curr is None:
  113. if prev.to < self.to:
  114. free_intervals.append([prev.to, self.to])
  115. else:
  116. if prev.to < curr.from_:
  117. free_intervals.append([prev.to, curr.from_])
  118.  
  119. prev = curr
  120.  
  121. return free_intervals
  122.  
  123.  
  124. def main():
  125. timeline = Line(from_=9, to=18)
  126. timeline.mark(from_=9, to=11, obj='Procrastinating')
  127. timeline.mark(from_=12, to=13, obj='Playing games')
  128.  
  129. assert timeline.can_mark(from_=11, to=12) == True
  130. assert timeline.can_mark(from_=10, to=11) == False
  131. assert timeline.can_mark(from_=11, to=13) == False
  132. assert timeline.get_free() == [[11, 12], [13, 18]]
  133. assert timeline.get(10).obj == 'Procrastinating'
  134. assert timeline.get(12).obj == 'Playing games'
  135.  
  136. for obj in timeline:
  137. print('From: {} To: {} Obj: {}'.format(obj.from_, obj.to, obj.obj))
  138.  
  139. try:
  140. timeline.mark(from_=10, to=12.5, obj='Playing games')
  141. except ValueError:
  142. print('passed')
  143.  
  144. try:
  145. timeline.mark(from_=9.5, to=10, obj='Playing games')
  146. except ValueError:
  147. print('passed')
  148.  
  149. try:
  150. timeline.mark(from_=5, to=6, obj='Playing games')
  151. except ValueError:
  152. print('passed')
  153.  
  154. try:
  155. timeline.get(11.5)
  156. except IndexError:
  157. print('passed')
  158.  
  159. try:
  160. timeline.get(13)
  161. except IndexError:
  162. print('passed')
  163.  
  164.  
  165. if __name__ == '__main__':
  166. main()
Add Comment
Please, Sign In to add comment