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
19.12.2024 11:21
19.12.2024 11:22
19.12.2024 11:24
19.12.2024 11:25
19.12.2024 11:27
19.12.2024 11:28
19.12.2024 11:29