Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
OOP. Chapter five solution in Clear category for Lightbulb Operating by swagg010164
from datetime import datetime, timedelta
from typing import List, Optional
class Lightbulb:
def __init__(self, start_watching, end_watching, operating):
self.state = 'off'
self.change_state_time = None
self.time_on = 0
self.start_watching = start_watching
self.end_watching = end_watching
self.operating = operating
self.intervals = []
def operating_deco(func):
def wrapper(self, date1, date2):
res = func(self, date1, date2)
if res:
self.intervals.append((date1, res))
return wrapper
@property
def get_start_times(self):
return [k[0] for k in self.intervals]
@property
def get_end_times(self):
return [k[1] for k in self.intervals]
def get_overall_time_on(self) -> int:
return self.time_on
@operating_deco
def check_operating(self, date1, date2):
if self.operating == timedelta(seconds=0):
return
if self.operating is None:
return date2
if date1 + self.operating < date2:
carry = self.operating
self.operating = timedelta(seconds=0)
return date1 + carry
self.operating -= (date2 - date1)
return date2
def normal_counter(self, date):
self.check_operating(self.change_state_time, date)
def only_start_watcher(self, date):
if self.start_watching > date:
return
if self.start_watching <= self.change_state_time:
return self.normal_counter(date)
self.check_operating(self.start_watching, date)
def start_and_end_watcher(self, date):
if self.start_watching <= self.change_state_time and self.end_watching <= self.change_state_time:
return
elif self.start_watching >= date and self.end_watching >= date:
return
elif self.start_watching >= self.change_state_time and self.end_watching <= date:
self.check_operating(self.start_watching, self.end_watching)
elif self.start_watching < self.change_state_time and self.end_watching > date:
self.normal_counter(date)
elif self.start_watching <= self.change_state_time < self.end_watching <= date:
self.check_operating(self.change_state_time, self.end_watching)
else:
self.check_operating(self.start_watching, date)
def change_state(self, date: datetime) -> None:
if self.state == 'on':
if self.start_watching is None and self.end_watching is None:
self.normal_counter(date)
elif self.start_watching is not None and self.end_watching is None:
self.only_start_watcher(date)
else:
self.start_and_end_watcher(date)
self.state = 'off'
else:
self.state = 'on'
self.change_state_time = date
def check_ligths_on(self):
if self.state == 'on':
if self.change_state_time <= self.start_watching:
self.check_operating(self.start_watching, self.end_watching)
if self.start_watching <= self.change_state_time < self.end_watching:
self.check_operating(self.change_state_time, self.end_watching)
def sum_light(els: List[datetime],
start_watching: Optional[datetime] = None,
end_watching: Optional[datetime] = None,
operating: Optional[timedelta] = None) -> int:
bulb_hash_map = dict()
for elem in els:
if isinstance(elem, tuple):
date, num = elem
else:
date, num = elem, 1
if num in bulb_hash_map:
bulb_hash_map[num].change_state(date)
else:
bulb = Lightbulb(start_watching, end_watching, operating)
bulb.change_state(date)
bulb_hash_map[num] = bulb
for key in bulb_hash_map.keys():
bulb_hash_map[key].check_ligths_on()
start_times, end_times = [], []
for bulb in bulb_hash_map.values():
start_times += bulb.get_start_times
end_times += bulb.get_end_times
start_times.sort()
end_times.sort()
ans = 0
if not start_times and not end_times:
return 0
start_pointer, ans_for_start, end_pointer = 0, start_times[0], 0
while start_pointer < len(start_times):
if end_times[end_pointer] <= start_times[start_pointer]:
while end_pointer < len(end_times) and end_times[end_pointer] <= start_times[start_pointer]:
end_pointer += 1
ans += (end_times[end_pointer - 1] - ans_for_start).total_seconds()
ans_for_start = start_times[start_pointer]
start_pointer += 1
if end_pointer < len(end_times):
ans += (end_times[-1] - ans_for_start).total_seconds()
return int(ans)
Jan. 7, 2022
Comments: