Домашни > Подаръци ще има за всички от сърце > Решения > Решението на Павел Петков

Резултати
10 точки от тестове
1 точки от учител

11 точки общо

20 успешни теста
0 неуспешни теста
Код
Скрий всички коментари

  1import re
  2
  3EXPIRED_KID_YEARS_OLD = 5  # :)
  4BAD_PRESENT_FOR_BAD_KID = "coal"
  5
  6
  7class Singleton(type):
  8    _instances = {}
  9
 10    def __call__(cls, *args, **kwargs):
 11        if cls not in cls._instances:
 12            instance = super().__call__(*args, **kwargs)
 13            cls._instances[cls] = instance
 14        return cls._instances[cls]
 15
 16
 17class Santa(metaclass=Singleton):
 18    kids_present_dict = {}
 19    punished_kids = set()
 20    kids = []
 21
 22    def __call__(self, child, wish: str):
 23        present = self.__extract_present(wish)
 24        self.kids_present_dict[child] = present
 25
 26    def __matmul__(self, wish):
 27        if not isinstance(wish, str):
 28            raise NotImplemented
 29        child_id = self.__extract_child(wish)
 30        child = self.__extract_child_by_id(child_id)
 31        present = self.__extract_present(wish)
 32        self.kids_present_dict[child] = present
 33
 34    def __extract_child_by_id(self, child_id):
 35        return list(filter(lambda child: id(child) == child_id, self.kids))[0]
 36
 37    @staticmethod
 38    def __extract_present(wish):
 39        pattern = r"(['\"])([a-zA-Z0-9\s]+)\1"
 40        present_matched = re.search(pattern, wish)
 41        return present_matched.group(2)
 42
 43    @staticmethod
 44    def __extract_child(wish):
 45        pattern = r"^\s*(\d+)\s*$"
 46        child_id_matched = re.search(pattern, wish, re.MULTILINE)
 47        return int(child_id_matched.group(1))
 48
 49    def __iter__(self):
 50        return self.SantaIterator(list(self.kids_present_dict.values()))
 51
 52    def xmas(self):
 53        self.__grow_kids()
 54        if not self.kids_present_dict:
 55            return
 56        for kid, present in self.__generate_kids_presents().items():
 57            kid(present)
 58        self.punished_kids.clear()
 59        self.kids_present_dict.clear()
 60
 61    def __grow_kids(self):
 62        for kid in self.kids:
 63            kid.years_old += 1
 64
 65    def __generate_kids_presents(self):
 66        most_wanted_present = self.__get_most_wanted_present()
 67        result = {}
 68        for kid in self.kids:
 69            if kid.years_old > EXPIRED_KID_YEARS_OLD:
 70                continue
 71            elif kid in self.punished_kids:
 72                result[kid] = BAD_PRESENT_FOR_BAD_KID
 73            elif kid not in self.kids_present_dict:
 74                result[kid] = most_wanted_present
 75            else:
 76                result[kid] = self.kids_present_dict[kid]
 77        return result
 78
 79    def __get_most_wanted_present(self):
 80        result = {}
 81        for key, value in self.kids_present_dict.items():
 82            if value in result:
 83                result[value] += 1
 84            else:
 85                result[value] = 1
 86        return max(result, key=lambda k: result[k])
 87
 88    class SantaIterator:
 89        def __init__(self, wishes):
 90            self._wishes = wishes
 91            self._index = 0
 92
 93        def __iter__(self):
 94            return self
 95
 96        def __next__(self):
 97            if self._index < len(self._wishes):
 98                result = self._wishes[self._index]
 99                self._index += 1
100                return result
101            self.index = 0  # Ако някой реши че не иска да вика нова инстанция
102
103            raise StopIteration
104
105
106class Kid(type):
107    santa = Santa()
108
109    def __new__(cls, name, bases, attrs):
110        if "__call__" not in attrs:
111            raise NotImplementedError("Trqbva da bude implemented")
112
113        for key, value in attrs.items():
114            if callable(value) and not key.startswith("__") and not key.startswith("_"):
115                attrs[key] = cls.wrapped_error_behavior(value)
116        return super().__new__(cls, name, bases, attrs)
117
118    def __call__(cls, *args, **kwargs):
119        instance = super().__call__(*args, **kwargs)
120        instance.years_old = 0
121        Santa.kids.append(instance)
122        return instance
123
124    @staticmethod
125    def wrapped_error_behavior(method):
126        def wrapper(*args, **kwargs):
127            try:
128                return method(*args, **kwargs)
129            except Exception as error:
130                kid_instance = args[0]  # kid self
131                Santa.punished_kids.add(kid_instance)
132                raise error
133
134        return wrapper
135
136    def __hash__(self):
137        return id(self)
138
139    def __eq__(self, other):
140        return id(self) == id(other)

....................
----------------------------------------------------------------------
Ran 20 tests in 0.084s

OK

Дискусия
История
Това решение има само една версия.