1import re
2from collections import OrderedDict
3from random import randint
4
5
6def class_method_naughty_decorator(func):
7 def wrapper(self, *args, **kwargs):
8 try:
9 res = func(self, *args, **kwargs)
10 return res
11 except:
12 self.is_naughty = True
13 raise
14 return wrapper
15
16def init_decorator(init_func):
17 def wrapper(self, *args, **kwargs):
18 if init_func:
19 init_func(self, *args, **kwargs)
20 self.is_naughty = False
21 self.age = 0
22 Santa.detect_new_kid(self)
23 return wrapper
24
25
26class SingletonMeta(type):
27
28 _all_instances = {}
29
30 def __call__(cls, *args, **kwargs):
31 if cls not in cls._all_instances:
32 instance = super().__call__(*args, **kwargs)
33 cls._all_instances[cls] = instance
34 return cls._all_instances[cls]
35
36
37class Kid(type):
38
39 def __new__(cls, name, bases, attr_dict):
40 if '__call__' not in attr_dict:
41 raise NotImplementedError("OK stands for OBICHAM KOCETO <3")
42
43 def age_up(self):
44 self.age += 1
45
46 def be_good(self):
47 self.is_naughty = False
48
49 original_init = attr_dict.get('__init__', None)
50
51 attr_dict['__init__'] = init_decorator(original_init)
52 attr_dict['age_up'] = age_up
53 attr_dict['be_good'] = be_good
54
55 for method_name, method in attr_dict.items():
56 if callable(method) and not method_name.startswith('_'):
57 attr_dict[method_name] = class_method_naughty_decorator(method)
58
59 return type.__new__(cls, name, bases, attr_dict)
60
61
62class Santa(metaclass=SingletonMeta):
63
64 _all_kids = {} # id -> instance
65 _gifts = OrderedDict() # id -> gift
66
67 @classmethod
68 def detect_new_kid(cls, kid):
69 cls._all_kids[id(kid)] = kid
70
71 @staticmethod
72 def _get_signature(wish):
73 target = re.search(r'^\s*(\d+)\s*$', wish, re.MULTILINE)
74 return target.group(1)
75
76 @staticmethod
77 def _get_gift(wish):
78 if res := re.search(r'"([A-Za-z0-9 ]+)"', wish):
79 return res.group(1)
80 elif res := re.search(r'\'([A-Za-z0-9 ]+)\'', wish):
81 return res.group(1)
82
83 def __call__(self, child, call):
84 self._gifts[id(child)] = self._get_gift(call)
85
86 def __matmul__(self, letter):
87 signature = int(self._get_signature(letter))
88 self._gifts[signature] = self._get_gift(letter)
89
90 def __iter__(self):
91 return SantaIter(list(self._gifts.values()))
92
93 def _post_xmas(self):
94 """Age up all kids and make them well-behaved again"""
95
96 for kid in self._all_kids.values():
97 kid.age_up()
98 kid.be_good()
99
100 self._gifts.clear()
101
102 def _get_most_frequent_gifts(self):
103
104 freq_dict = {}
105
106 for gift in self._gifts.values():
107 if gift not in freq_dict:
108 freq_dict[gift] = 1
109 else:
110 freq_dict[gift] += 1
111
112 max_freq = max(freq_dict.values())
113
114 return [gift for gift, count in freq_dict.items() if count == max_freq]
115
116 def _give_gifts(self):
117 most_freq_gifts = self._get_most_frequent_gifts()
118
119 for kid_id, kid in self._all_kids.items():
120 if kid.age < 5:
121 if kid.is_naughty:
122 kid('coal')
123 elif kid_id in self._gifts.keys():
124 kid(self._gifts[kid_id])
125 else:
126 random_idx = randint(0, len(most_freq_gifts) - 1)
127 kid(most_freq_gifts[random_idx])
128
129 def xmas(self):
130 if self._gifts:
131 self._give_gifts()
132 self._post_xmas()
133
134
135class SantaIter:
136
137 def __init__(self, gifts):
138 self.gifts = gifts
139 self.idx = 0
140
141 def __iter__(self):
142 return self
143
144 def __next__(self):
145 if self.idx < len(self.gifts):
146 curr = self.gifts[self.idx]
147 self.idx += 1
148 return curr
149 else:
150 self.idx = 0
151 raise StopIteration
....................
----------------------------------------------------------------------
Ran 20 tests in 0.024s
OK
Ивайло Кънчев
19.12.2024 00:15Надявам се чудесата в метакласа да не счупят тестовете по някаква причина :D
|
f | 1 | import re | f | 1 | import re |
2 | from collections import OrderedDict | 2 | from collections import OrderedDict | ||
3 | from random import randint | 3 | from random import randint | ||
4 | 4 | ||||
n | n | 5 | |||
5 | def class_method_naughty_decorator(func): | 6 | def class_method_naughty_decorator(func): | ||
6 | def wrapper(self, *args, **kwargs): | 7 | def wrapper(self, *args, **kwargs): | ||
7 | try: | 8 | try: | ||
n | 8 | ans = func(self, *args, **kwargs) | n | 9 | res = func(self, *args, **kwargs) |
9 | return ans | 10 | return res | ||
10 | except Exception: | 11 | except: | ||
11 | self.is_naughty = True | 12 | self.is_naughty = True | ||
12 | raise | 13 | raise | ||
13 | return wrapper | 14 | return wrapper | ||
14 | 15 | ||||
15 | def init_decorator(init_func): | 16 | def init_decorator(init_func): | ||
16 | def wrapper(self, *args, **kwargs): | 17 | def wrapper(self, *args, **kwargs): | ||
17 | if init_func: | 18 | if init_func: | ||
18 | init_func(self, *args, **kwargs) | 19 | init_func(self, *args, **kwargs) | ||
19 | self.is_naughty = False | 20 | self.is_naughty = False | ||
20 | self.age = 0 | 21 | self.age = 0 | ||
21 | Santa.detect_new_kid(self) | 22 | Santa.detect_new_kid(self) | ||
22 | return wrapper | 23 | return wrapper | ||
23 | 24 | ||||
24 | 25 | ||||
25 | class SingletonMeta(type): | 26 | class SingletonMeta(type): | ||
26 | 27 | ||||
27 | _all_instances = {} | 28 | _all_instances = {} | ||
28 | 29 | ||||
29 | def __call__(cls, *args, **kwargs): | 30 | def __call__(cls, *args, **kwargs): | ||
30 | if cls not in cls._all_instances: | 31 | if cls not in cls._all_instances: | ||
31 | instance = super().__call__(*args, **kwargs) | 32 | instance = super().__call__(*args, **kwargs) | ||
32 | cls._all_instances[cls] = instance | 33 | cls._all_instances[cls] = instance | ||
33 | return cls._all_instances[cls] | 34 | return cls._all_instances[cls] | ||
34 | 35 | ||||
35 | 36 | ||||
36 | class Kid(type): | 37 | class Kid(type): | ||
37 | 38 | ||||
38 | def __new__(cls, name, bases, attr_dict): | 39 | def __new__(cls, name, bases, attr_dict): | ||
39 | if '__call__' not in attr_dict: | 40 | if '__call__' not in attr_dict: | ||
40 | raise NotImplementedError("OK stands for OBICHAM KOCETO <3") | 41 | raise NotImplementedError("OK stands for OBICHAM KOCETO <3") | ||
41 | 42 | ||||
42 | def age_up(self): | 43 | def age_up(self): | ||
43 | self.age += 1 | 44 | self.age += 1 | ||
44 | 45 | ||||
45 | def be_good(self): | 46 | def be_good(self): | ||
46 | self.is_naughty = False | 47 | self.is_naughty = False | ||
47 | 48 | ||||
48 | original_init = attr_dict.get('__init__', None) | 49 | original_init = attr_dict.get('__init__', None) | ||
49 | 50 | ||||
50 | attr_dict['__init__'] = init_decorator(original_init) | 51 | attr_dict['__init__'] = init_decorator(original_init) | ||
51 | attr_dict['age_up'] = age_up | 52 | attr_dict['age_up'] = age_up | ||
52 | attr_dict['be_good'] = be_good | 53 | attr_dict['be_good'] = be_good | ||
53 | 54 | ||||
54 | for method_name, method in attr_dict.items(): | 55 | for method_name, method in attr_dict.items(): | ||
n | 55 | if callable(method) and not method_name.startswith('_') and not method_name.startswith('__'): | n | 56 | if callable(method) and not method_name.startswith('_'): |
56 | attr_dict[method_name] = class_method_naughty_decorator(method) | 57 | attr_dict[method_name] = class_method_naughty_decorator(method) | ||
57 | 58 | ||||
58 | return type.__new__(cls, name, bases, attr_dict) | 59 | return type.__new__(cls, name, bases, attr_dict) | ||
59 | 60 | ||||
60 | 61 | ||||
61 | class Santa(metaclass=SingletonMeta): | 62 | class Santa(metaclass=SingletonMeta): | ||
62 | 63 | ||||
63 | _all_kids = {} # id -> instance | 64 | _all_kids = {} # id -> instance | ||
64 | _gifts = OrderedDict() # id -> gift | 65 | _gifts = OrderedDict() # id -> gift | ||
65 | 66 | ||||
66 | @classmethod | 67 | @classmethod | ||
67 | def detect_new_kid(cls, kid): | 68 | def detect_new_kid(cls, kid): | ||
68 | cls._all_kids[id(kid)] = kid | 69 | cls._all_kids[id(kid)] = kid | ||
69 | 70 | ||||
70 | @staticmethod | 71 | @staticmethod | ||
71 | def _get_signature(wish): | 72 | def _get_signature(wish): | ||
72 | target = re.search(r'^\s*(\d+)\s*$', wish, re.MULTILINE) | 73 | target = re.search(r'^\s*(\d+)\s*$', wish, re.MULTILINE) | ||
73 | return target.group(1) | 74 | return target.group(1) | ||
74 | 75 | ||||
75 | @staticmethod | 76 | @staticmethod | ||
76 | def _get_gift(wish): | 77 | def _get_gift(wish): | ||
77 | if res := re.search(r'"([A-Za-z0-9 ]+)"', wish): | 78 | if res := re.search(r'"([A-Za-z0-9 ]+)"', wish): | ||
78 | return res.group(1) | 79 | return res.group(1) | ||
79 | elif res := re.search(r'\'([A-Za-z0-9 ]+)\'', wish): | 80 | elif res := re.search(r'\'([A-Za-z0-9 ]+)\'', wish): | ||
80 | return res.group(1) | 81 | return res.group(1) | ||
81 | 82 | ||||
82 | def __call__(self, child, call): | 83 | def __call__(self, child, call): | ||
83 | self._gifts[id(child)] = self._get_gift(call) | 84 | self._gifts[id(child)] = self._get_gift(call) | ||
84 | 85 | ||||
85 | def __matmul__(self, letter): | 86 | def __matmul__(self, letter): | ||
86 | signature = int(self._get_signature(letter)) | 87 | signature = int(self._get_signature(letter)) | ||
87 | self._gifts[signature] = self._get_gift(letter) | 88 | self._gifts[signature] = self._get_gift(letter) | ||
88 | 89 | ||||
89 | def __iter__(self): | 90 | def __iter__(self): | ||
90 | return SantaIter(list(self._gifts.values())) | 91 | return SantaIter(list(self._gifts.values())) | ||
91 | 92 | ||||
92 | def _post_xmas(self): | 93 | def _post_xmas(self): | ||
93 | """Age up all kids and make them well-behaved again""" | 94 | """Age up all kids and make them well-behaved again""" | ||
94 | 95 | ||||
95 | for kid in self._all_kids.values(): | 96 | for kid in self._all_kids.values(): | ||
96 | kid.age_up() | 97 | kid.age_up() | ||
97 | kid.be_good() | 98 | kid.be_good() | ||
98 | 99 | ||||
99 | self._gifts.clear() | 100 | self._gifts.clear() | ||
100 | 101 | ||||
101 | def _get_most_frequent_gifts(self): | 102 | def _get_most_frequent_gifts(self): | ||
102 | 103 | ||||
103 | freq_dict = {} | 104 | freq_dict = {} | ||
n | 104 | most_freq_gifts = [] | n | ||
105 | 105 | ||||
106 | for gift in self._gifts.values(): | 106 | for gift in self._gifts.values(): | ||
107 | if gift not in freq_dict: | 107 | if gift not in freq_dict: | ||
108 | freq_dict[gift] = 1 | 108 | freq_dict[gift] = 1 | ||
109 | else: | 109 | else: | ||
110 | freq_dict[gift] += 1 | 110 | freq_dict[gift] += 1 | ||
111 | 111 | ||||
112 | max_freq = max(freq_dict.values()) | 112 | max_freq = max(freq_dict.values()) | ||
113 | 113 | ||||
n | 114 | for gift, freq in freq_dict.items(): | n | 114 | return [gift for gift, count in freq_dict.items() if count == max_freq] |
115 | if freq == max_freq: | ||||
116 | most_freq_gifts.append(gift) | ||||
117 | |||||
118 | return most_freq_gifts | ||||
119 | 115 | ||||
120 | def _give_gifts(self): | 116 | def _give_gifts(self): | ||
121 | most_freq_gifts = self._get_most_frequent_gifts() | 117 | most_freq_gifts = self._get_most_frequent_gifts() | ||
122 | 118 | ||||
123 | for kid_id, kid in self._all_kids.items(): | 119 | for kid_id, kid in self._all_kids.items(): | ||
124 | if kid.age < 5: | 120 | if kid.age < 5: | ||
125 | if kid.is_naughty: | 121 | if kid.is_naughty: | ||
126 | kid('coal') | 122 | kid('coal') | ||
127 | elif kid_id in self._gifts.keys(): | 123 | elif kid_id in self._gifts.keys(): | ||
128 | kid(self._gifts[kid_id]) | 124 | kid(self._gifts[kid_id]) | ||
129 | else: | 125 | else: | ||
130 | random_idx = randint(0, len(most_freq_gifts) - 1) | 126 | random_idx = randint(0, len(most_freq_gifts) - 1) | ||
131 | kid(most_freq_gifts[random_idx]) | 127 | kid(most_freq_gifts[random_idx]) | ||
132 | 128 | ||||
133 | def xmas(self): | 129 | def xmas(self): | ||
134 | if self._gifts: | 130 | if self._gifts: | ||
135 | self._give_gifts() | 131 | self._give_gifts() | ||
136 | self._post_xmas() | 132 | self._post_xmas() | ||
137 | 133 | ||||
138 | 134 | ||||
139 | class SantaIter: | 135 | class SantaIter: | ||
140 | 136 | ||||
141 | def __init__(self, gifts): | 137 | def __init__(self, gifts): | ||
142 | self.gifts = gifts | 138 | self.gifts = gifts | ||
143 | self.idx = 0 | 139 | self.idx = 0 | ||
144 | 140 | ||||
145 | def __iter__(self): | 141 | def __iter__(self): | ||
146 | return self | 142 | return self | ||
147 | 143 | ||||
148 | def __next__(self): | 144 | def __next__(self): | ||
149 | if self.idx < len(self.gifts): | 145 | if self.idx < len(self.gifts): | ||
150 | curr = self.gifts[self.idx] | 146 | curr = self.gifts[self.idx] | ||
151 | self.idx += 1 | 147 | self.idx += 1 | ||
152 | return curr | 148 | return curr | ||
153 | else: | 149 | else: | ||
154 | self.idx = 0 | 150 | self.idx = 0 | ||
155 | raise StopIteration | 151 | raise StopIteration | ||
t | 156 | t |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | import re | f | 1 | import re |
2 | from collections import OrderedDict | 2 | from collections import OrderedDict | ||
3 | from random import randint | 3 | from random import randint | ||
4 | 4 | ||||
5 | def class_method_naughty_decorator(func): | 5 | def class_method_naughty_decorator(func): | ||
6 | def wrapper(self, *args, **kwargs): | 6 | def wrapper(self, *args, **kwargs): | ||
7 | try: | 7 | try: | ||
8 | ans = func(self, *args, **kwargs) | 8 | ans = func(self, *args, **kwargs) | ||
9 | return ans | 9 | return ans | ||
10 | except Exception: | 10 | except Exception: | ||
11 | self.is_naughty = True | 11 | self.is_naughty = True | ||
12 | raise | 12 | raise | ||
13 | return wrapper | 13 | return wrapper | ||
14 | 14 | ||||
15 | def init_decorator(init_func): | 15 | def init_decorator(init_func): | ||
16 | def wrapper(self, *args, **kwargs): | 16 | def wrapper(self, *args, **kwargs): | ||
17 | if init_func: | 17 | if init_func: | ||
18 | init_func(self, *args, **kwargs) | 18 | init_func(self, *args, **kwargs) | ||
19 | self.is_naughty = False | 19 | self.is_naughty = False | ||
n | 20 | self.age = 1 | n | 20 | self.age = 0 |
21 | Santa.detect_new_kid(self) | 21 | Santa.detect_new_kid(self) | ||
22 | return wrapper | 22 | return wrapper | ||
23 | 23 | ||||
24 | 24 | ||||
25 | class SingletonMeta(type): | 25 | class SingletonMeta(type): | ||
26 | 26 | ||||
27 | _all_instances = {} | 27 | _all_instances = {} | ||
28 | 28 | ||||
29 | def __call__(cls, *args, **kwargs): | 29 | def __call__(cls, *args, **kwargs): | ||
30 | if cls not in cls._all_instances: | 30 | if cls not in cls._all_instances: | ||
31 | instance = super().__call__(*args, **kwargs) | 31 | instance = super().__call__(*args, **kwargs) | ||
32 | cls._all_instances[cls] = instance | 32 | cls._all_instances[cls] = instance | ||
33 | return cls._all_instances[cls] | 33 | return cls._all_instances[cls] | ||
34 | 34 | ||||
35 | 35 | ||||
36 | class Kid(type): | 36 | class Kid(type): | ||
37 | 37 | ||||
38 | def __new__(cls, name, bases, attr_dict): | 38 | def __new__(cls, name, bases, attr_dict): | ||
39 | if '__call__' not in attr_dict: | 39 | if '__call__' not in attr_dict: | ||
40 | raise NotImplementedError("OK stands for OBICHAM KOCETO <3") | 40 | raise NotImplementedError("OK stands for OBICHAM KOCETO <3") | ||
41 | 41 | ||||
42 | def age_up(self): | 42 | def age_up(self): | ||
43 | self.age += 1 | 43 | self.age += 1 | ||
44 | 44 | ||||
45 | def be_good(self): | 45 | def be_good(self): | ||
46 | self.is_naughty = False | 46 | self.is_naughty = False | ||
47 | 47 | ||||
48 | original_init = attr_dict.get('__init__', None) | 48 | original_init = attr_dict.get('__init__', None) | ||
49 | 49 | ||||
50 | attr_dict['__init__'] = init_decorator(original_init) | 50 | attr_dict['__init__'] = init_decorator(original_init) | ||
51 | attr_dict['age_up'] = age_up | 51 | attr_dict['age_up'] = age_up | ||
52 | attr_dict['be_good'] = be_good | 52 | attr_dict['be_good'] = be_good | ||
53 | 53 | ||||
54 | for method_name, method in attr_dict.items(): | 54 | for method_name, method in attr_dict.items(): | ||
55 | if callable(method) and not method_name.startswith('_') and not method_name.startswith('__'): | 55 | if callable(method) and not method_name.startswith('_') and not method_name.startswith('__'): | ||
56 | attr_dict[method_name] = class_method_naughty_decorator(method) | 56 | attr_dict[method_name] = class_method_naughty_decorator(method) | ||
57 | 57 | ||||
58 | return type.__new__(cls, name, bases, attr_dict) | 58 | return type.__new__(cls, name, bases, attr_dict) | ||
59 | 59 | ||||
60 | 60 | ||||
61 | class Santa(metaclass=SingletonMeta): | 61 | class Santa(metaclass=SingletonMeta): | ||
62 | 62 | ||||
63 | _all_kids = {} # id -> instance | 63 | _all_kids = {} # id -> instance | ||
64 | _gifts = OrderedDict() # id -> gift | 64 | _gifts = OrderedDict() # id -> gift | ||
65 | 65 | ||||
66 | @classmethod | 66 | @classmethod | ||
67 | def detect_new_kid(cls, kid): | 67 | def detect_new_kid(cls, kid): | ||
68 | cls._all_kids[id(kid)] = kid | 68 | cls._all_kids[id(kid)] = kid | ||
69 | 69 | ||||
70 | @staticmethod | 70 | @staticmethod | ||
71 | def _get_signature(wish): | 71 | def _get_signature(wish): | ||
72 | target = re.search(r'^\s*(\d+)\s*$', wish, re.MULTILINE) | 72 | target = re.search(r'^\s*(\d+)\s*$', wish, re.MULTILINE) | ||
73 | return target.group(1) | 73 | return target.group(1) | ||
74 | 74 | ||||
75 | @staticmethod | 75 | @staticmethod | ||
76 | def _get_gift(wish): | 76 | def _get_gift(wish): | ||
77 | if res := re.search(r'"([A-Za-z0-9 ]+)"', wish): | 77 | if res := re.search(r'"([A-Za-z0-9 ]+)"', wish): | ||
78 | return res.group(1) | 78 | return res.group(1) | ||
79 | elif res := re.search(r'\'([A-Za-z0-9 ]+)\'', wish): | 79 | elif res := re.search(r'\'([A-Za-z0-9 ]+)\'', wish): | ||
80 | return res.group(1) | 80 | return res.group(1) | ||
81 | 81 | ||||
82 | def __call__(self, child, call): | 82 | def __call__(self, child, call): | ||
83 | self._gifts[id(child)] = self._get_gift(call) | 83 | self._gifts[id(child)] = self._get_gift(call) | ||
84 | 84 | ||||
85 | def __matmul__(self, letter): | 85 | def __matmul__(self, letter): | ||
86 | signature = int(self._get_signature(letter)) | 86 | signature = int(self._get_signature(letter)) | ||
87 | self._gifts[signature] = self._get_gift(letter) | 87 | self._gifts[signature] = self._get_gift(letter) | ||
88 | 88 | ||||
89 | def __iter__(self): | 89 | def __iter__(self): | ||
90 | return SantaIter(list(self._gifts.values())) | 90 | return SantaIter(list(self._gifts.values())) | ||
91 | 91 | ||||
92 | def _post_xmas(self): | 92 | def _post_xmas(self): | ||
93 | """Age up all kids and make them well-behaved again""" | 93 | """Age up all kids and make them well-behaved again""" | ||
94 | 94 | ||||
95 | for kid in self._all_kids.values(): | 95 | for kid in self._all_kids.values(): | ||
96 | kid.age_up() | 96 | kid.age_up() | ||
97 | kid.be_good() | 97 | kid.be_good() | ||
98 | 98 | ||||
99 | self._gifts.clear() | 99 | self._gifts.clear() | ||
100 | 100 | ||||
101 | def _get_most_frequent_gifts(self): | 101 | def _get_most_frequent_gifts(self): | ||
102 | 102 | ||||
103 | freq_dict = {} | 103 | freq_dict = {} | ||
104 | most_freq_gifts = [] | 104 | most_freq_gifts = [] | ||
105 | 105 | ||||
106 | for gift in self._gifts.values(): | 106 | for gift in self._gifts.values(): | ||
107 | if gift not in freq_dict: | 107 | if gift not in freq_dict: | ||
108 | freq_dict[gift] = 1 | 108 | freq_dict[gift] = 1 | ||
109 | else: | 109 | else: | ||
110 | freq_dict[gift] += 1 | 110 | freq_dict[gift] += 1 | ||
111 | 111 | ||||
112 | max_freq = max(freq_dict.values()) | 112 | max_freq = max(freq_dict.values()) | ||
113 | 113 | ||||
114 | for gift, freq in freq_dict.items(): | 114 | for gift, freq in freq_dict.items(): | ||
115 | if freq == max_freq: | 115 | if freq == max_freq: | ||
116 | most_freq_gifts.append(gift) | 116 | most_freq_gifts.append(gift) | ||
117 | 117 | ||||
118 | return most_freq_gifts | 118 | return most_freq_gifts | ||
119 | 119 | ||||
120 | def _give_gifts(self): | 120 | def _give_gifts(self): | ||
121 | most_freq_gifts = self._get_most_frequent_gifts() | 121 | most_freq_gifts = self._get_most_frequent_gifts() | ||
122 | 122 | ||||
123 | for kid_id, kid in self._all_kids.items(): | 123 | for kid_id, kid in self._all_kids.items(): | ||
t | 124 | if kid.age <= 5: | t | 124 | if kid.age < 5: |
125 | if kid.is_naughty: | 125 | if kid.is_naughty: | ||
126 | kid('coal') | 126 | kid('coal') | ||
127 | elif kid_id in self._gifts.keys(): | 127 | elif kid_id in self._gifts.keys(): | ||
128 | kid(self._gifts[kid_id]) | 128 | kid(self._gifts[kid_id]) | ||
129 | else: | 129 | else: | ||
130 | random_idx = randint(0, len(most_freq_gifts) - 1) | 130 | random_idx = randint(0, len(most_freq_gifts) - 1) | ||
131 | kid(most_freq_gifts[random_idx]) | 131 | kid(most_freq_gifts[random_idx]) | ||
132 | 132 | ||||
133 | def xmas(self): | 133 | def xmas(self): | ||
134 | if self._gifts: | 134 | if self._gifts: | ||
135 | self._give_gifts() | 135 | self._give_gifts() | ||
136 | self._post_xmas() | 136 | self._post_xmas() | ||
137 | 137 | ||||
138 | 138 | ||||
139 | class SantaIter: | 139 | class SantaIter: | ||
140 | 140 | ||||
141 | def __init__(self, gifts): | 141 | def __init__(self, gifts): | ||
142 | self.gifts = gifts | 142 | self.gifts = gifts | ||
143 | self.idx = 0 | 143 | self.idx = 0 | ||
144 | 144 | ||||
145 | def __iter__(self): | 145 | def __iter__(self): | ||
146 | return self | 146 | return self | ||
147 | 147 | ||||
148 | def __next__(self): | 148 | def __next__(self): | ||
149 | if self.idx < len(self.gifts): | 149 | if self.idx < len(self.gifts): | ||
150 | curr = self.gifts[self.idx] | 150 | curr = self.gifts[self.idx] | ||
151 | self.idx += 1 | 151 | self.idx += 1 | ||
152 | return curr | 152 | return curr | ||
153 | else: | 153 | else: | ||
154 | self.idx = 0 | 154 | self.idx = 0 | ||
155 | raise StopIteration | 155 | raise StopIteration | ||
156 | 156 |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | import re | f | 1 | import re |
2 | from collections import OrderedDict | 2 | from collections import OrderedDict | ||
3 | from random import randint | 3 | from random import randint | ||
4 | 4 | ||||
5 | def class_method_naughty_decorator(func): | 5 | def class_method_naughty_decorator(func): | ||
6 | def wrapper(self, *args, **kwargs): | 6 | def wrapper(self, *args, **kwargs): | ||
7 | try: | 7 | try: | ||
8 | ans = func(self, *args, **kwargs) | 8 | ans = func(self, *args, **kwargs) | ||
9 | return ans | 9 | return ans | ||
10 | except Exception: | 10 | except Exception: | ||
11 | self.is_naughty = True | 11 | self.is_naughty = True | ||
12 | raise | 12 | raise | ||
13 | return wrapper | 13 | return wrapper | ||
14 | 14 | ||||
15 | def init_decorator(init_func): | 15 | def init_decorator(init_func): | ||
16 | def wrapper(self, *args, **kwargs): | 16 | def wrapper(self, *args, **kwargs): | ||
17 | if init_func: | 17 | if init_func: | ||
18 | init_func(self, *args, **kwargs) | 18 | init_func(self, *args, **kwargs) | ||
19 | self.is_naughty = False | 19 | self.is_naughty = False | ||
20 | self.age = 1 | 20 | self.age = 1 | ||
21 | Santa.detect_new_kid(self) | 21 | Santa.detect_new_kid(self) | ||
22 | return wrapper | 22 | return wrapper | ||
23 | 23 | ||||
24 | 24 | ||||
25 | class SingletonMeta(type): | 25 | class SingletonMeta(type): | ||
26 | 26 | ||||
27 | _all_instances = {} | 27 | _all_instances = {} | ||
28 | 28 | ||||
29 | def __call__(cls, *args, **kwargs): | 29 | def __call__(cls, *args, **kwargs): | ||
30 | if cls not in cls._all_instances: | 30 | if cls not in cls._all_instances: | ||
31 | instance = super().__call__(*args, **kwargs) | 31 | instance = super().__call__(*args, **kwargs) | ||
32 | cls._all_instances[cls] = instance | 32 | cls._all_instances[cls] = instance | ||
33 | return cls._all_instances[cls] | 33 | return cls._all_instances[cls] | ||
34 | 34 | ||||
35 | 35 | ||||
36 | class Kid(type): | 36 | class Kid(type): | ||
37 | 37 | ||||
38 | def __new__(cls, name, bases, attr_dict): | 38 | def __new__(cls, name, bases, attr_dict): | ||
39 | if '__call__' not in attr_dict: | 39 | if '__call__' not in attr_dict: | ||
40 | raise NotImplementedError("OK stands for OBICHAM KOCETO <3") | 40 | raise NotImplementedError("OK stands for OBICHAM KOCETO <3") | ||
41 | 41 | ||||
42 | def age_up(self): | 42 | def age_up(self): | ||
43 | self.age += 1 | 43 | self.age += 1 | ||
44 | 44 | ||||
45 | def be_good(self): | 45 | def be_good(self): | ||
46 | self.is_naughty = False | 46 | self.is_naughty = False | ||
47 | 47 | ||||
48 | original_init = attr_dict.get('__init__', None) | 48 | original_init = attr_dict.get('__init__', None) | ||
49 | 49 | ||||
50 | attr_dict['__init__'] = init_decorator(original_init) | 50 | attr_dict['__init__'] = init_decorator(original_init) | ||
51 | attr_dict['age_up'] = age_up | 51 | attr_dict['age_up'] = age_up | ||
52 | attr_dict['be_good'] = be_good | 52 | attr_dict['be_good'] = be_good | ||
53 | 53 | ||||
54 | for method_name, method in attr_dict.items(): | 54 | for method_name, method in attr_dict.items(): | ||
55 | if callable(method) and not method_name.startswith('_') and not method_name.startswith('__'): | 55 | if callable(method) and not method_name.startswith('_') and not method_name.startswith('__'): | ||
56 | attr_dict[method_name] = class_method_naughty_decorator(method) | 56 | attr_dict[method_name] = class_method_naughty_decorator(method) | ||
57 | 57 | ||||
58 | return type.__new__(cls, name, bases, attr_dict) | 58 | return type.__new__(cls, name, bases, attr_dict) | ||
59 | 59 | ||||
60 | 60 | ||||
61 | class Santa(metaclass=SingletonMeta): | 61 | class Santa(metaclass=SingletonMeta): | ||
62 | 62 | ||||
63 | _all_kids = {} # id -> instance | 63 | _all_kids = {} # id -> instance | ||
64 | _gifts = OrderedDict() # id -> gift | 64 | _gifts = OrderedDict() # id -> gift | ||
65 | 65 | ||||
66 | @classmethod | 66 | @classmethod | ||
67 | def detect_new_kid(cls, kid): | 67 | def detect_new_kid(cls, kid): | ||
68 | cls._all_kids[id(kid)] = kid | 68 | cls._all_kids[id(kid)] = kid | ||
69 | 69 | ||||
70 | @staticmethod | 70 | @staticmethod | ||
71 | def _get_signature(wish): | 71 | def _get_signature(wish): | ||
72 | target = re.search(r'^\s*(\d+)\s*$', wish, re.MULTILINE) | 72 | target = re.search(r'^\s*(\d+)\s*$', wish, re.MULTILINE) | ||
73 | return target.group(1) | 73 | return target.group(1) | ||
74 | 74 | ||||
75 | @staticmethod | 75 | @staticmethod | ||
76 | def _get_gift(wish): | 76 | def _get_gift(wish): | ||
77 | if res := re.search(r'"([A-Za-z0-9 ]+)"', wish): | 77 | if res := re.search(r'"([A-Za-z0-9 ]+)"', wish): | ||
78 | return res.group(1) | 78 | return res.group(1) | ||
79 | elif res := re.search(r'\'([A-Za-z0-9 ]+)\'', wish): | 79 | elif res := re.search(r'\'([A-Za-z0-9 ]+)\'', wish): | ||
80 | return res.group(1) | 80 | return res.group(1) | ||
81 | 81 | ||||
82 | def __call__(self, child, call): | 82 | def __call__(self, child, call): | ||
83 | self._gifts[id(child)] = self._get_gift(call) | 83 | self._gifts[id(child)] = self._get_gift(call) | ||
84 | 84 | ||||
85 | def __matmul__(self, letter): | 85 | def __matmul__(self, letter): | ||
86 | signature = int(self._get_signature(letter)) | 86 | signature = int(self._get_signature(letter)) | ||
87 | self._gifts[signature] = self._get_gift(letter) | 87 | self._gifts[signature] = self._get_gift(letter) | ||
88 | 88 | ||||
89 | def __iter__(self): | 89 | def __iter__(self): | ||
90 | return SantaIter(list(self._gifts.values())) | 90 | return SantaIter(list(self._gifts.values())) | ||
91 | 91 | ||||
92 | def _post_xmas(self): | 92 | def _post_xmas(self): | ||
93 | """Age up all kids and make them well-behaved again""" | 93 | """Age up all kids and make them well-behaved again""" | ||
94 | 94 | ||||
95 | for kid in self._all_kids.values(): | 95 | for kid in self._all_kids.values(): | ||
96 | kid.age_up() | 96 | kid.age_up() | ||
97 | kid.be_good() | 97 | kid.be_good() | ||
98 | 98 | ||||
99 | self._gifts.clear() | 99 | self._gifts.clear() | ||
100 | 100 | ||||
101 | def _get_most_frequent_gifts(self): | 101 | def _get_most_frequent_gifts(self): | ||
102 | 102 | ||||
103 | freq_dict = {} | 103 | freq_dict = {} | ||
104 | most_freq_gifts = [] | 104 | most_freq_gifts = [] | ||
105 | 105 | ||||
106 | for gift in self._gifts.values(): | 106 | for gift in self._gifts.values(): | ||
107 | if gift not in freq_dict: | 107 | if gift not in freq_dict: | ||
108 | freq_dict[gift] = 1 | 108 | freq_dict[gift] = 1 | ||
109 | else: | 109 | else: | ||
110 | freq_dict[gift] += 1 | 110 | freq_dict[gift] += 1 | ||
111 | 111 | ||||
112 | max_freq = max(freq_dict.values()) | 112 | max_freq = max(freq_dict.values()) | ||
113 | 113 | ||||
114 | for gift, freq in freq_dict.items(): | 114 | for gift, freq in freq_dict.items(): | ||
115 | if freq == max_freq: | 115 | if freq == max_freq: | ||
116 | most_freq_gifts.append(gift) | 116 | most_freq_gifts.append(gift) | ||
117 | 117 | ||||
118 | return most_freq_gifts | 118 | return most_freq_gifts | ||
119 | 119 | ||||
120 | def _give_gifts(self): | 120 | def _give_gifts(self): | ||
121 | most_freq_gifts = self._get_most_frequent_gifts() | 121 | most_freq_gifts = self._get_most_frequent_gifts() | ||
122 | 122 | ||||
123 | for kid_id, kid in self._all_kids.items(): | 123 | for kid_id, kid in self._all_kids.items(): | ||
124 | if kid.age <= 5: | 124 | if kid.age <= 5: | ||
125 | if kid.is_naughty: | 125 | if kid.is_naughty: | ||
126 | kid('coal') | 126 | kid('coal') | ||
127 | elif kid_id in self._gifts.keys(): | 127 | elif kid_id in self._gifts.keys(): | ||
128 | kid(self._gifts[kid_id]) | 128 | kid(self._gifts[kid_id]) | ||
129 | else: | 129 | else: | ||
130 | random_idx = randint(0, len(most_freq_gifts) - 1) | 130 | random_idx = randint(0, len(most_freq_gifts) - 1) | ||
131 | kid(most_freq_gifts[random_idx]) | 131 | kid(most_freq_gifts[random_idx]) | ||
132 | 132 | ||||
133 | def xmas(self): | 133 | def xmas(self): | ||
134 | if self._gifts: | 134 | if self._gifts: | ||
135 | self._give_gifts() | 135 | self._give_gifts() | ||
136 | self._post_xmas() | 136 | self._post_xmas() | ||
137 | 137 | ||||
138 | 138 | ||||
139 | class SantaIter: | 139 | class SantaIter: | ||
140 | 140 | ||||
141 | def __init__(self, gifts): | 141 | def __init__(self, gifts): | ||
142 | self.gifts = gifts | 142 | self.gifts = gifts | ||
143 | self.idx = 0 | 143 | self.idx = 0 | ||
144 | 144 | ||||
n | n | 145 | def __iter__(self): | ||
146 | return self | ||||
147 | |||||
145 | def __next__(self): | 148 | def __next__(self): | ||
146 | if self.idx < len(self.gifts): | 149 | if self.idx < len(self.gifts): | ||
147 | curr = self.gifts[self.idx] | 150 | curr = self.gifts[self.idx] | ||
148 | self.idx += 1 | 151 | self.idx += 1 | ||
149 | return curr | 152 | return curr | ||
150 | else: | 153 | else: | ||
t | t | 154 | self.idx = 0 | ||
151 | raise StopIteration | 155 | raise StopIteration | ||
152 | 156 |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
20.12.2024 17:06