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

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

10 точки общо

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

  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
История

f1import ref1import re
2from collections import OrderedDict2from collections import OrderedDict
3from random import randint3from random import randint
44
nn5 
5def class_method_naughty_decorator(func):6def class_method_naughty_decorator(func):
6    def wrapper(self, *args, **kwargs):7    def wrapper(self, *args, **kwargs):
7        try:8        try:
n8            ans = func(self, *args, **kwargs)n9            res = func(self, *args, **kwargs)
9            return ans10            return res
10        except Exception:11        except:
11            self.is_naughty = True12            self.is_naughty = True
12            raise13            raise
13    return wrapper14    return wrapper
1415
15def init_decorator(init_func):16def 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 = False20        self.is_naughty = False
20        self.age = 021        self.age = 0
21        Santa.detect_new_kid(self)22        Santa.detect_new_kid(self)
22    return wrapper23    return wrapper
2324
2425
25class SingletonMeta(type):26class SingletonMeta(type):
2627
27    _all_instances = {}28    _all_instances = {}
2829
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] = instance33            cls._all_instances[cls] = instance
33        return cls._all_instances[cls]34        return cls._all_instances[cls]
3435
3536
36class Kid(type):37class Kid(type):
3738
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")
4142
42        def age_up(self):43        def age_up(self):
43            self.age += 144            self.age += 1
4445
45        def be_good(self):46        def be_good(self):
46            self.is_naughty = False47            self.is_naughty = False
4748
48        original_init = attr_dict.get('__init__', None)49        original_init = attr_dict.get('__init__', None)
4950
50        attr_dict['__init__'] = init_decorator(original_init)51        attr_dict['__init__'] = init_decorator(original_init)
51        attr_dict['age_up'] = age_up52        attr_dict['age_up'] = age_up
52        attr_dict['be_good'] = be_good53        attr_dict['be_good'] = be_good
5354
54        for method_name, method in attr_dict.items():55        for method_name, method in attr_dict.items():
n55            if callable(method) and not method_name.startswith('_') and not method_name.startswith('__'):n56            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)
5758
58        return type.__new__(cls, name, bases, attr_dict)59        return type.__new__(cls, name, bases, attr_dict)
5960
6061
61class Santa(metaclass=SingletonMeta):62class Santa(metaclass=SingletonMeta):
6263
63    _all_kids = {} # id -> instance64    _all_kids = {} # id -> instance
64    _gifts = OrderedDict() # id -> gift65    _gifts = OrderedDict() # id -> gift
6566
66    @classmethod67    @classmethod
67    def detect_new_kid(cls, kid):68    def detect_new_kid(cls, kid):
68        cls._all_kids[id(kid)] = kid69        cls._all_kids[id(kid)] = kid
6970
70    @staticmethod71    @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)
7475
75    @staticmethod76    @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)
8182
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)
8485
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)
8889
89    def __iter__(self):90    def __iter__(self):
90        return SantaIter(list(self._gifts.values()))91        return SantaIter(list(self._gifts.values()))
9192
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"""
9495
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()
9899
99        self._gifts.clear()100        self._gifts.clear()
100101
101    def _get_most_frequent_gifts(self):102    def _get_most_frequent_gifts(self):
102103
103        freq_dict = {}104        freq_dict = {}
n104        most_freq_gifts = []n
105105
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] = 1108                freq_dict[gift] = 1
109            else:109            else:
110                freq_dict[gift] += 1110                freq_dict[gift] += 1
111111
112        max_freq = max(freq_dict.values())112        max_freq = max(freq_dict.values())
113113
n114        for gift, freq in freq_dict.items():n114        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
119115
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()
122118
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])
132128
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()
137133
138134
139class SantaIter:135class SantaIter:
140136
141    def __init__(self, gifts):137    def __init__(self, gifts):
142        self.gifts = gifts138        self.gifts = gifts
143        self.idx = 0139        self.idx = 0
144140
145    def __iter__(self):141    def __iter__(self):
146        return self142        return self
147143
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 += 1147            self.idx += 1
152            return curr148            return curr
153        else:149        else:
154            self.idx = 0150            self.idx = 0
155            raise StopIteration151            raise StopIteration
t156 t
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import ref1import re
2from collections import OrderedDict2from collections import OrderedDict
3from random import randint3from random import randint
44
5def class_method_naughty_decorator(func):5def 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 ans9            return ans
10        except Exception:10        except Exception:
11            self.is_naughty = True11            self.is_naughty = True
12            raise12            raise
13    return wrapper13    return wrapper
1414
15def init_decorator(init_func):15def 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 = False19        self.is_naughty = False
n20        self.age = 1n20        self.age = 0
21        Santa.detect_new_kid(self)21        Santa.detect_new_kid(self)
22    return wrapper22    return wrapper
2323
2424
25class SingletonMeta(type):25class SingletonMeta(type):
2626
27    _all_instances = {}27    _all_instances = {}
2828
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] = instance32            cls._all_instances[cls] = instance
33        return cls._all_instances[cls]33        return cls._all_instances[cls]
3434
3535
36class Kid(type):36class Kid(type):
3737
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")
4141
42        def age_up(self):42        def age_up(self):
43            self.age += 143            self.age += 1
4444
45        def be_good(self):45        def be_good(self):
46            self.is_naughty = False46            self.is_naughty = False
4747
48        original_init = attr_dict.get('__init__', None)48        original_init = attr_dict.get('__init__', None)
4949
50        attr_dict['__init__'] = init_decorator(original_init)50        attr_dict['__init__'] = init_decorator(original_init)
51        attr_dict['age_up'] = age_up51        attr_dict['age_up'] = age_up
52        attr_dict['be_good'] = be_good52        attr_dict['be_good'] = be_good
5353
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)
5757
58        return type.__new__(cls, name, bases, attr_dict)58        return type.__new__(cls, name, bases, attr_dict)
5959
6060
61class Santa(metaclass=SingletonMeta):61class Santa(metaclass=SingletonMeta):
6262
63    _all_kids = {} # id -> instance63    _all_kids = {} # id -> instance
64    _gifts = OrderedDict() # id -> gift64    _gifts = OrderedDict() # id -> gift
6565
66    @classmethod66    @classmethod
67    def detect_new_kid(cls, kid):67    def detect_new_kid(cls, kid):
68        cls._all_kids[id(kid)] = kid68        cls._all_kids[id(kid)] = kid
6969
70    @staticmethod70    @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)
7474
75    @staticmethod75    @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)
8181
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)
8484
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)
8888
89    def __iter__(self):89    def __iter__(self):
90        return SantaIter(list(self._gifts.values()))90        return SantaIter(list(self._gifts.values()))
9191
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"""
9494
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()
9898
99        self._gifts.clear()99        self._gifts.clear()
100100
101    def _get_most_frequent_gifts(self):101    def _get_most_frequent_gifts(self):
102102
103        freq_dict = {}103        freq_dict = {}
104        most_freq_gifts = []104        most_freq_gifts = []
105105
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] = 1108                freq_dict[gift] = 1
109            else:109            else:
110                freq_dict[gift] += 1110                freq_dict[gift] += 1
111111
112        max_freq = max(freq_dict.values())112        max_freq = max(freq_dict.values())
113113
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)
117117
118        return most_freq_gifts118        return most_freq_gifts
119119
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()
122122
123        for kid_id, kid in self._all_kids.items():123        for kid_id, kid in self._all_kids.items():
t124            if kid.age <= 5:t124            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])
132132
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()
137137
138138
139class SantaIter:139class SantaIter:
140140
141    def __init__(self, gifts):141    def __init__(self, gifts):
142        self.gifts = gifts142        self.gifts = gifts
143        self.idx = 0143        self.idx = 0
144144
145    def __iter__(self):145    def __iter__(self):
146        return self146        return self
147147
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 += 1151            self.idx += 1
152            return curr152            return curr
153        else:153        else:
154            self.idx = 0154            self.idx = 0
155            raise StopIteration155            raise StopIteration
156156
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import ref1import re
2from collections import OrderedDict2from collections import OrderedDict
3from random import randint3from random import randint
44
5def class_method_naughty_decorator(func):5def 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 ans9            return ans
10        except Exception:10        except Exception:
11            self.is_naughty = True11            self.is_naughty = True
12            raise12            raise
13    return wrapper13    return wrapper
1414
15def init_decorator(init_func):15def 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 = False19        self.is_naughty = False
20        self.age = 120        self.age = 1
21        Santa.detect_new_kid(self)21        Santa.detect_new_kid(self)
22    return wrapper22    return wrapper
2323
2424
25class SingletonMeta(type):25class SingletonMeta(type):
2626
27    _all_instances = {}27    _all_instances = {}
2828
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] = instance32            cls._all_instances[cls] = instance
33        return cls._all_instances[cls]33        return cls._all_instances[cls]
3434
3535
36class Kid(type):36class Kid(type):
3737
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")
4141
42        def age_up(self):42        def age_up(self):
43            self.age += 143            self.age += 1
4444
45        def be_good(self):45        def be_good(self):
46            self.is_naughty = False46            self.is_naughty = False
4747
48        original_init = attr_dict.get('__init__', None)48        original_init = attr_dict.get('__init__', None)
4949
50        attr_dict['__init__'] = init_decorator(original_init)50        attr_dict['__init__'] = init_decorator(original_init)
51        attr_dict['age_up'] = age_up51        attr_dict['age_up'] = age_up
52        attr_dict['be_good'] = be_good52        attr_dict['be_good'] = be_good
5353
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)
5757
58        return type.__new__(cls, name, bases, attr_dict)58        return type.__new__(cls, name, bases, attr_dict)
5959
6060
61class Santa(metaclass=SingletonMeta):61class Santa(metaclass=SingletonMeta):
6262
63    _all_kids = {} # id -> instance63    _all_kids = {} # id -> instance
64    _gifts = OrderedDict() # id -> gift64    _gifts = OrderedDict() # id -> gift
6565
66    @classmethod66    @classmethod
67    def detect_new_kid(cls, kid):67    def detect_new_kid(cls, kid):
68        cls._all_kids[id(kid)] = kid68        cls._all_kids[id(kid)] = kid
6969
70    @staticmethod70    @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)
7474
75    @staticmethod75    @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)
8181
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)
8484
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)
8888
89    def __iter__(self):89    def __iter__(self):
90        return SantaIter(list(self._gifts.values()))90        return SantaIter(list(self._gifts.values()))
9191
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"""
9494
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()
9898
99        self._gifts.clear()99        self._gifts.clear()
100100
101    def _get_most_frequent_gifts(self):101    def _get_most_frequent_gifts(self):
102102
103        freq_dict = {}103        freq_dict = {}
104        most_freq_gifts = []104        most_freq_gifts = []
105105
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] = 1108                freq_dict[gift] = 1
109            else:109            else:
110                freq_dict[gift] += 1110                freq_dict[gift] += 1
111111
112        max_freq = max(freq_dict.values())112        max_freq = max(freq_dict.values())
113113
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)
117117
118        return most_freq_gifts118        return most_freq_gifts
119119
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()
122122
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])
132132
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()
137137
138138
139class SantaIter:139class SantaIter:
140140
141    def __init__(self, gifts):141    def __init__(self, gifts):
142        self.gifts = gifts142        self.gifts = gifts
143        self.idx = 0143        self.idx = 0
144144
nn145    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 += 1151            self.idx += 1
149            return curr152            return curr
150        else:153        else:
tt154            self.idx = 0
151            raise StopIteration155            raise StopIteration
152156
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op