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

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

10 точки общо

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

  1import random
  2import re
  3import threading
  4import time
  5from collections import defaultdict, Counter, OrderedDict
  6from datetime import datetime
  7
  8
  9class CSI:
 10    """Central Santa Intelligence."""
 11
 12    _instance = None
 13    _naughty_list = defaultdict(OrderedDict)
 14    _individuals_under_observation = {}
 15
 16    def __new__(cls, *args, **kwargs):
 17        """There can be only one CSI."""
 18        if cls._instance is None:
 19            cls._instance = super().__new__(cls, *args, **kwargs)
 20        return cls._instance
 21
 22    @classmethod
 23    def notify_about_new_baby(cls, individual):
 24        """Here's your package of earthworms. How are Kevin and the kids?"""
 25        cls._individuals_under_observation[id(individual)] = individual
 26
 27        def notify_about_transgression(method):
 28            """CSI sees EVERYTHING."""
 29            def decorated(*args, **kwargs):
 30                try:
 31                    result = method(individual, *args, **kwargs)
 32                except Exception as err:
 33                    time_of_naughtiness = datetime.now()
 34                    print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.")
 35                    CSI._naughty_list[individual][time_of_naughtiness] = err
 36                    raise
 37                return result
 38            return decorated
 39
 40        for attr_name, obj in type(individual).__dict__.items():
 41            if callable(obj) and not attr_name.startswith('_'):
 42                setattr(individual, attr_name, notify_about_transgression(obj))
 43
 44    @property
 45    def all_individuals(self):
 46        return self._individuals_under_observation.values()
 47
 48    def identify_sender(self, text):
 49        """Santa leaves espionage to the CSI."""
 50        sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None)
 51        return self._individuals_under_observation[sender_id]
 52
 53    def is_naughty(self, individual):
 54        """Assess if the individual has erred this year."""
 55        return individual in self._naughty_list
 56
 57    def prepare_for_next_christmass(self):
 58        """Update the ages of people and give everyone another chance for the new year."""
 59        self._naughty_list = defaultdict(OrderedDict)
 60
 61
 62class Santa:
 63    """Saint Nicholas... Or however he's called in your culture."""
 64
 65    _csi = CSI()
 66    _wishes = OrderedDict()
 67    _instance = None
 68    _santas_private_list = {}
 69
 70    def __new__(cls, *args, **kwargs):
 71        """There can be only one Santa!"""
 72        if cls._instance is None:
 73            cls._instance = super().__new__(cls, *args, **kwargs)
 74        return cls._instance
 75
 76    def __call__(self, kid, request):
 77        """Call santa with a gift request."""
 78        self._wishes[kid] = self._extract_gift(request)
 79
 80    def __matmul__(self, letter):
 81        """Write a letter to Santa."""
 82        kid = self._csi.identify_sender(letter)
 83        self._wishes[kid] = self._extract_gift(letter)
 84
 85    def __iter__(self):
 86        """Santa is iterable, if you didn't know."""
 87        return iter(self._wishes.values())
 88
 89    def _extract_gift(self, text):
 90        """Santa takes notes of all gifts."""
 91        return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None
 92
 93    def xmas(self):
 94        """Deliver gifts."""
 95        most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None
 96        # Make sure to give presents to the ones who called or sent letters first
 97        kids_with_wishes = list(self._wishes.keys())
 98        kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes))
 99        for kid in kids_with_wishes + kids_without_wishes:
100            if kid.age >= 18 and self._csi.is_naughty(kid):
101                self._santas_private_list.add(kid)
102                continue
103            # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad
104            if kids_with_wishes and kid.age < 5:
105                if self._csi.is_naughty(kid):
106                    present = 'coal'
107                else:
108                    present = self._wishes.get(kid, most_wanted)
109                kid(present)
110            else:
111                kid(None) # A Christmas is a Christmas even without the presents
112        self._prepare_for_next_christmass()
113
114    def _prepare_for_next_christmass(self):
115        """Prepare for next Christmas by giving everyone the benefit of the doubt."""
116        self._csi.prepare_for_next_christmass()
117        self._wishes = OrderedDict()
118
119
120class Kid(type):
121
122    @staticmethod
123    def _better_init(original_init):
124        """Because sometimes people need a push in the right direction."""
125        def decorated(self, *args, **kwargs):
126            original_init(self, *args, **kwargs)
127            Person.__init__(self)
128        return decorated
129
130    @staticmethod
131    def _better_new(*genetic_information):
132        """Because this is how babies are made, canonically speaking."""
133        return Stork.deliver_baby(genetic_information)
134
135    @staticmethod
136    def _better_call(original_call): # Saul
137        """Add an increase of age to the original call."""
138        def decorated(self, *args, **kwargs):
139            result = original_call(self, *args, **kwargs)
140            self.age += 1
141            return result
142        return decorated
143
144    def __new__(cls, name, bases, attr_dict):
145        """Create a type of kid."""
146        if '__call__' not in attr_dict:
147            raise NotImplementedError
148        attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None))
149        attr_dict['__new__'] = cls._better_new
150        attr_dict['__call__'] = cls._better_call(attr_dict['__call__'])
151        return super().__new__(cls, name, bases + (Person,), attr_dict)
152
153
154class Person:
155    """What is a person?"""
156
157    def __init__(self):
158        """Initialize age for each person."""
159        self.age = 0
160
161    def __hash__(self):
162        """Can you hash a person?"""
163        return hash(id(self))
164
165
166class Stork:
167    """A main worker in the baby-delivery service."""
168
169    _available_storks = []
170
171    def __init__(self):
172        """Initialize carrying space for babies for the current stork."""
173        self.baby = []
174
175    def _procure_a_baby(self, genetic_information):
176        """Where from? No idea."""
177        # Part of an old implementation, left here only for the joke
178        # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he
179        self.baby = [object.__new__(*genetic_information)]
180        self._____notify_CSI()
181
182    def _____notify_CSI(self):
183        """Nothing to see here, move along."""
184        CSI.notify_about_new_baby(self.baby[0])
185
186    def _deliver_baby(self):
187        """Hehe, *pop*."""
188        return self.baby.pop()
189
190    @classmethod
191    def deliver_baby(cls, genetic_information):
192        """Deliver a baby to the happy parents."""
193        threading.Thread(target=cls._request_storks).start()
194        while not cls._available_storks:
195            print("There are no storks available, please wait as your call is important to us!")
196            time.sleep(0.03)
197        return cls._dispatch_stork(genetic_information)
198
199    @classmethod
200    def _request_storks(cls):
201        """Request for adding storks to the stork pool."""
202        time.sleep(0.09)
203        storks = [cls() for _ in range(random.randint(1, 10))]
204        cls._available_storks.extend(storks)
205        print("Thank you for your patience. Storks are ready for dispatch!")
206
207    @classmethod
208    def _dispatch_stork(cls, genetic_information):
209        """Dispatch an available stork in the area."""
210        stork_index = random.randint(0, len(cls._available_storks) - 1)
211        stork = cls._available_storks.pop(stork_index)
212        stork._procure_a_baby(genetic_information)
213        print("Stork dispatched, please wait for your delivery.")
214        return stork._deliver_baby()

Timed out.

Дискусия
Георги Кунчев
19.12.2024 15:46

I've got you, bro! Here - take these 10 bonus points.
Виктор Бечев
19.12.2024 14:32

Лол, това заслужавам, таймаут. :rofl:
История

f1import randomf1import random
2import re2import re
3import threading3import threading
4import time4import time
5from collections import defaultdict, Counter, OrderedDict5from collections import defaultdict, Counter, OrderedDict
6from datetime import datetime6from datetime import datetime
77
88
9class CSI:9class CSI:
10    """Central Santa Intelligence."""10    """Central Santa Intelligence."""
1111
12    _instance = None12    _instance = None
13    _naughty_list = defaultdict(OrderedDict)13    _naughty_list = defaultdict(OrderedDict)
14    _individuals_under_observation = {}14    _individuals_under_observation = {}
1515
16    def __new__(cls, *args, **kwargs):16    def __new__(cls, *args, **kwargs):
17        """There can be only one CSI."""17        """There can be only one CSI."""
18        if cls._instance is None:18        if cls._instance is None:
19            cls._instance = super().__new__(cls, *args, **kwargs)19            cls._instance = super().__new__(cls, *args, **kwargs)
20        return cls._instance20        return cls._instance
2121
22    @classmethod22    @classmethod
23    def notify_about_new_baby(cls, individual):23    def notify_about_new_baby(cls, individual):
24        """Here's your package of earthworms. How are Kevin and the kids?"""24        """Here's your package of earthworms. How are Kevin and the kids?"""
25        cls._individuals_under_observation[id(individual)] = individual25        cls._individuals_under_observation[id(individual)] = individual
2626
27        def notify_about_transgression(method):27        def notify_about_transgression(method):
28            """CSI sees EVERYTHING."""28            """CSI sees EVERYTHING."""
29            def decorated(*args, **kwargs):29            def decorated(*args, **kwargs):
30                try:30                try:
31                    result = method(individual, *args, **kwargs)31                    result = method(individual, *args, **kwargs)
32                except Exception as err:32                except Exception as err:
33                    time_of_naughtiness = datetime.now()33                    time_of_naughtiness = datetime.now()
34                    print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.")34                    print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.")
35                    CSI._naughty_list[individual][time_of_naughtiness] = err35                    CSI._naughty_list[individual][time_of_naughtiness] = err
36                    raise36                    raise
37                return result37                return result
38            return decorated38            return decorated
3939
40        for attr_name, obj in type(individual).__dict__.items():40        for attr_name, obj in type(individual).__dict__.items():
41            if callable(obj) and not attr_name.startswith('_'):41            if callable(obj) and not attr_name.startswith('_'):
42                setattr(individual, attr_name, notify_about_transgression(obj))42                setattr(individual, attr_name, notify_about_transgression(obj))
4343
44    @property44    @property
45    def all_individuals(self):45    def all_individuals(self):
46        return self._individuals_under_observation.values()46        return self._individuals_under_observation.values()
4747
48    def identify_sender(self, text):48    def identify_sender(self, text):
49        """Santa leaves espionage to the CSI."""49        """Santa leaves espionage to the CSI."""
50        sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None)50        sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None)
51        return self._individuals_under_observation[sender_id]51        return self._individuals_under_observation[sender_id]
5252
53    def is_naughty(self, individual):53    def is_naughty(self, individual):
54        """Assess if the individual has erred this year."""54        """Assess if the individual has erred this year."""
55        return individual in self._naughty_list55        return individual in self._naughty_list
5656
57    def prepare_for_next_christmass(self):57    def prepare_for_next_christmass(self):
58        """Update the ages of people and give everyone another chance for the new year."""58        """Update the ages of people and give everyone another chance for the new year."""
59        self._naughty_list = defaultdict(OrderedDict)59        self._naughty_list = defaultdict(OrderedDict)
6060
6161
62class Santa:62class Santa:
63    """Saint Nicholas... Or however he's called in your culture."""63    """Saint Nicholas... Or however he's called in your culture."""
6464
65    _csi = CSI()65    _csi = CSI()
66    _wishes = OrderedDict()66    _wishes = OrderedDict()
67    _instance = None67    _instance = None
68    _santas_private_list = {}68    _santas_private_list = {}
6969
70    def __new__(cls, *args, **kwargs):70    def __new__(cls, *args, **kwargs):
71        """There can be only one Santa!"""71        """There can be only one Santa!"""
72        if cls._instance is None:72        if cls._instance is None:
73            cls._instance = super().__new__(cls, *args, **kwargs)73            cls._instance = super().__new__(cls, *args, **kwargs)
74        return cls._instance74        return cls._instance
7575
76    def __call__(self, kid, request):76    def __call__(self, kid, request):
77        """Call santa with a gift request."""77        """Call santa with a gift request."""
78        self._wishes[kid] = self._extract_gift(request)78        self._wishes[kid] = self._extract_gift(request)
7979
80    def __matmul__(self, letter):80    def __matmul__(self, letter):
81        """Write a letter to Santa."""81        """Write a letter to Santa."""
82        kid = self._csi.identify_sender(letter)82        kid = self._csi.identify_sender(letter)
83        self._wishes[kid] = self._extract_gift(letter)83        self._wishes[kid] = self._extract_gift(letter)
8484
85    def __iter__(self):85    def __iter__(self):
86        """Santa is iterable, if you didn't know."""86        """Santa is iterable, if you didn't know."""
87        return iter(self._wishes.values())87        return iter(self._wishes.values())
8888
89    def _extract_gift(self, text):89    def _extract_gift(self, text):
90        """Santa takes notes of all gifts."""90        """Santa takes notes of all gifts."""
91        return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None91        return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None
9292
93    def xmas(self):93    def xmas(self):
94        """Deliver gifts."""94        """Deliver gifts."""
95        most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None95        most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None
96        # Make sure to give presents to the ones who called or sent letters first96        # Make sure to give presents to the ones who called or sent letters first
97        kids_with_wishes = list(self._wishes.keys())97        kids_with_wishes = list(self._wishes.keys())
98        kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes))98        kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes))
99        for kid in kids_with_wishes + kids_without_wishes:99        for kid in kids_with_wishes + kids_without_wishes:
100            if kid.age >= 18 and self._csi.is_naughty(kid):100            if kid.age >= 18 and self._csi.is_naughty(kid):
101                self._santas_private_list.add(kid)101                self._santas_private_list.add(kid)
102                continue102                continue
103            # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad103            # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad
104            if kids_with_wishes and kid.age < 5:104            if kids_with_wishes and kid.age < 5:
105                if self._csi.is_naughty(kid):105                if self._csi.is_naughty(kid):
106                    present = 'coal'106                    present = 'coal'
107                else:107                else:
108                    present = self._wishes.get(kid, most_wanted)108                    present = self._wishes.get(kid, most_wanted)
109                kid(present)109                kid(present)
110            else:110            else:
111                kid(None) # A Christmas is a Christmas even without the presents111                kid(None) # A Christmas is a Christmas even without the presents
112        self._prepare_for_next_christmass()112        self._prepare_for_next_christmass()
113113
114    def _prepare_for_next_christmass(self):114    def _prepare_for_next_christmass(self):
115        """Prepare for next Christmas by giving everyone the benefit of the doubt."""115        """Prepare for next Christmas by giving everyone the benefit of the doubt."""
116        self._csi.prepare_for_next_christmass()116        self._csi.prepare_for_next_christmass()
117        self._wishes = OrderedDict()117        self._wishes = OrderedDict()
118118
119119
120class Kid(type):120class Kid(type):
121121
122    @staticmethod122    @staticmethod
123    def _better_init(original_init):123    def _better_init(original_init):
124        """Because sometimes people need a push in the right direction."""124        """Because sometimes people need a push in the right direction."""
125        def decorated(self, *args, **kwargs):125        def decorated(self, *args, **kwargs):
126            original_init(self, *args, **kwargs)126            original_init(self, *args, **kwargs)
127            Person.__init__(self)127            Person.__init__(self)
128        return decorated128        return decorated
129129
130    @staticmethod130    @staticmethod
131    def _better_new(*genetic_information):131    def _better_new(*genetic_information):
132        """Because this is how babies are made, canonically speaking."""132        """Because this is how babies are made, canonically speaking."""
133        return Stork.deliver_baby(genetic_information)133        return Stork.deliver_baby(genetic_information)
134134
135    @staticmethod135    @staticmethod
136    def _better_call(original_call): # Saul136    def _better_call(original_call): # Saul
137        """Add an increase of age to the original call."""137        """Add an increase of age to the original call."""
138        def decorated(self, *args, **kwargs):138        def decorated(self, *args, **kwargs):
139            result = original_call(self, *args, **kwargs)139            result = original_call(self, *args, **kwargs)
140            self.age += 1140            self.age += 1
141            return result141            return result
142        return decorated142        return decorated
143143
144    def __new__(cls, name, bases, attr_dict):144    def __new__(cls, name, bases, attr_dict):
145        """Create a type of kid."""145        """Create a type of kid."""
146        if '__call__' not in attr_dict:146        if '__call__' not in attr_dict:
147            raise NotImplementedError147            raise NotImplementedError
148        attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None))148        attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None))
149        attr_dict['__new__'] = cls._better_new149        attr_dict['__new__'] = cls._better_new
150        attr_dict['__call__'] = cls._better_call(attr_dict['__call__'])150        attr_dict['__call__'] = cls._better_call(attr_dict['__call__'])
151        return super().__new__(cls, name, bases + (Person,), attr_dict)151        return super().__new__(cls, name, bases + (Person,), attr_dict)
152152
153153
154class Person:154class Person:
155    """What is a person?"""155    """What is a person?"""
156156
157    def __init__(self):157    def __init__(self):
158        """Initialize age for each person."""158        """Initialize age for each person."""
159        self.age = 0159        self.age = 0
160160
161    def __hash__(self):161    def __hash__(self):
162        """Can you hash a person?"""162        """Can you hash a person?"""
163        return hash(id(self))163        return hash(id(self))
164164
165165
166class Stork:166class Stork:
167    """A main worker in the baby-delivery service."""167    """A main worker in the baby-delivery service."""
168168
169    _available_storks = []169    _available_storks = []
170170
171    def __init__(self):171    def __init__(self):
172        """Initialize carrying space for babies for the current stork."""172        """Initialize carrying space for babies for the current stork."""
173        self.baby = []173        self.baby = []
174174
175    def _procure_a_baby(self, genetic_information):175    def _procure_a_baby(self, genetic_information):
176        """Where from? No idea."""176        """Where from? No idea."""
177        # Part of an old implementation, left here only for the joke177        # Part of an old implementation, left here only for the joke
178        # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he178        # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he
179        self.baby = [object.__new__(*genetic_information)]179        self.baby = [object.__new__(*genetic_information)]
180        self._____notify_CSI()180        self._____notify_CSI()
181181
182    def _____notify_CSI(self):182    def _____notify_CSI(self):
t183        """Nothing to see here, move along,"""t183        """Nothing to see here, move along."""
184        CSI.notify_about_new_baby(self.baby[0])184        CSI.notify_about_new_baby(self.baby[0])
185185
186    def _deliver_baby(self):186    def _deliver_baby(self):
187        """Hehe, *pop*."""187        """Hehe, *pop*."""
188        return self.baby.pop()188        return self.baby.pop()
189189
190    @classmethod190    @classmethod
191    def deliver_baby(cls, genetic_information):191    def deliver_baby(cls, genetic_information):
192        """Deliver a baby to the happy parents."""192        """Deliver a baby to the happy parents."""
193        threading.Thread(target=cls._request_storks).start()193        threading.Thread(target=cls._request_storks).start()
194        while not cls._available_storks:194        while not cls._available_storks:
195            print("There are no storks available, please wait as your call is important to us!")195            print("There are no storks available, please wait as your call is important to us!")
196            time.sleep(0.03)196            time.sleep(0.03)
197        return cls._dispatch_stork(genetic_information)197        return cls._dispatch_stork(genetic_information)
198198
199    @classmethod199    @classmethod
200    def _request_storks(cls):200    def _request_storks(cls):
201        """Request for adding storks to the stork pool."""201        """Request for adding storks to the stork pool."""
202        time.sleep(0.09)202        time.sleep(0.09)
203        storks = [cls() for _ in range(random.randint(1, 10))]203        storks = [cls() for _ in range(random.randint(1, 10))]
204        cls._available_storks.extend(storks)204        cls._available_storks.extend(storks)
205        print("Thank you for your patience. Storks are ready for dispatch!")205        print("Thank you for your patience. Storks are ready for dispatch!")
206206
207    @classmethod207    @classmethod
208    def _dispatch_stork(cls, genetic_information):208    def _dispatch_stork(cls, genetic_information):
209        """Dispatch an available stork in the area."""209        """Dispatch an available stork in the area."""
210        stork_index = random.randint(0, len(cls._available_storks) - 1)210        stork_index = random.randint(0, len(cls._available_storks) - 1)
211        stork = cls._available_storks.pop(stork_index)211        stork = cls._available_storks.pop(stork_index)
212        stork._procure_a_baby(genetic_information)212        stork._procure_a_baby(genetic_information)
213        print("Stork dispatched, please wait for your delivery.")213        print("Stork dispatched, please wait for your delivery.")
214        return stork._deliver_baby()214        return stork._deliver_baby()
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import randomf1import random
2import re2import re
3import threading3import threading
4import time4import time
5from collections import defaultdict, Counter, OrderedDict5from collections import defaultdict, Counter, OrderedDict
6from datetime import datetime6from datetime import datetime
77
88
9class CSI:9class CSI:
10    """Central Santa Intelligence."""10    """Central Santa Intelligence."""
1111
12    _instance = None12    _instance = None
13    _naughty_list = defaultdict(OrderedDict)13    _naughty_list = defaultdict(OrderedDict)
14    _individuals_under_observation = {}14    _individuals_under_observation = {}
1515
16    def __new__(cls, *args, **kwargs):16    def __new__(cls, *args, **kwargs):
17        """There can be only one CSI."""17        """There can be only one CSI."""
18        if cls._instance is None:18        if cls._instance is None:
19            cls._instance = super().__new__(cls, *args, **kwargs)19            cls._instance = super().__new__(cls, *args, **kwargs)
20        return cls._instance20        return cls._instance
2121
22    @classmethod22    @classmethod
23    def notify_about_new_baby(cls, individual):23    def notify_about_new_baby(cls, individual):
24        """Here's your package of earthworms. How are Kevin and the kids?"""24        """Here's your package of earthworms. How are Kevin and the kids?"""
25        cls._individuals_under_observation[id(individual)] = individual25        cls._individuals_under_observation[id(individual)] = individual
2626
27        def notify_about_transgression(method):27        def notify_about_transgression(method):
28            """CSI sees EVERYTHING."""28            """CSI sees EVERYTHING."""
29            def decorated(*args, **kwargs):29            def decorated(*args, **kwargs):
30                try:30                try:
31                    result = method(individual, *args, **kwargs)31                    result = method(individual, *args, **kwargs)
32                except Exception as err:32                except Exception as err:
33                    time_of_naughtiness = datetime.now()33                    time_of_naughtiness = datetime.now()
34                    print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.")34                    print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.")
35                    CSI._naughty_list[individual][time_of_naughtiness] = err35                    CSI._naughty_list[individual][time_of_naughtiness] = err
36                    raise36                    raise
37                return result37                return result
38            return decorated38            return decorated
3939
40        for attr_name, obj in type(individual).__dict__.items():40        for attr_name, obj in type(individual).__dict__.items():
41            if callable(obj) and not attr_name.startswith('_'):41            if callable(obj) and not attr_name.startswith('_'):
42                setattr(individual, attr_name, notify_about_transgression(obj))42                setattr(individual, attr_name, notify_about_transgression(obj))
4343
44    @property44    @property
45    def all_individuals(self):45    def all_individuals(self):
46        return self._individuals_under_observation.values()46        return self._individuals_under_observation.values()
4747
48    def identify_sender(self, text):48    def identify_sender(self, text):
49        """Santa leaves espionage to the CSI."""49        """Santa leaves espionage to the CSI."""
50        sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None)50        sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None)
51        return self._individuals_under_observation[sender_id]51        return self._individuals_under_observation[sender_id]
5252
53    def is_naughty(self, individual):53    def is_naughty(self, individual):
54        """Assess if the individual has erred this year."""54        """Assess if the individual has erred this year."""
55        return individual in self._naughty_list55        return individual in self._naughty_list
5656
57    def prepare_for_next_christmass(self):57    def prepare_for_next_christmass(self):
58        """Update the ages of people and give everyone another chance for the new year."""58        """Update the ages of people and give everyone another chance for the new year."""
59        self._naughty_list = defaultdict(OrderedDict)59        self._naughty_list = defaultdict(OrderedDict)
6060
6161
62class Santa:62class Santa:
63    """Saint Nicholas... Or however he's called in your culture."""63    """Saint Nicholas... Or however he's called in your culture."""
6464
65    _csi = CSI()65    _csi = CSI()
66    _wishes = OrderedDict()66    _wishes = OrderedDict()
67    _instance = None67    _instance = None
68    _santas_private_list = {}68    _santas_private_list = {}
6969
70    def __new__(cls, *args, **kwargs):70    def __new__(cls, *args, **kwargs):
71        """There can be only one Santa!"""71        """There can be only one Santa!"""
72        if cls._instance is None:72        if cls._instance is None:
73            cls._instance = super().__new__(cls, *args, **kwargs)73            cls._instance = super().__new__(cls, *args, **kwargs)
74        return cls._instance74        return cls._instance
7575
76    def __call__(self, kid, request):76    def __call__(self, kid, request):
77        """Call santa with a gift request."""77        """Call santa with a gift request."""
78        self._wishes[kid] = self._extract_gift(request)78        self._wishes[kid] = self._extract_gift(request)
7979
80    def __matmul__(self, letter):80    def __matmul__(self, letter):
81        """Write a letter to Santa."""81        """Write a letter to Santa."""
82        kid = self._csi.identify_sender(letter)82        kid = self._csi.identify_sender(letter)
83        self._wishes[kid] = self._extract_gift(letter)83        self._wishes[kid] = self._extract_gift(letter)
8484
85    def __iter__(self):85    def __iter__(self):
n86        """Santa """n86        """Santa is iterable, if you didn't know."""
87        return iter(self._wishes.values())87        return iter(self._wishes.values())
8888
89    def _extract_gift(self, text):89    def _extract_gift(self, text):
90        """Santa takes notes of all gifts."""90        """Santa takes notes of all gifts."""
91        return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None91        return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None
9292
93    def xmas(self):93    def xmas(self):
94        """Deliver gifts."""94        """Deliver gifts."""
95        most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None95        most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None
96        # Make sure to give presents to the ones who called or sent letters first96        # Make sure to give presents to the ones who called or sent letters first
97        kids_with_wishes = list(self._wishes.keys())97        kids_with_wishes = list(self._wishes.keys())
98        kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes))98        kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes))
99        for kid in kids_with_wishes + kids_without_wishes:99        for kid in kids_with_wishes + kids_without_wishes:
100            if kid.age >= 18 and self._csi.is_naughty(kid):100            if kid.age >= 18 and self._csi.is_naughty(kid):
101                self._santas_private_list.add(kid)101                self._santas_private_list.add(kid)
102                continue102                continue
103            # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad103            # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad
104            if kids_with_wishes and kid.age < 5:104            if kids_with_wishes and kid.age < 5:
105                if self._csi.is_naughty(kid):105                if self._csi.is_naughty(kid):
106                    present = 'coal'106                    present = 'coal'
107                else:107                else:
108                    present = self._wishes.get(kid, most_wanted)108                    present = self._wishes.get(kid, most_wanted)
109                kid(present)109                kid(present)
110            else:110            else:
111                kid(None) # A Christmas is a Christmas even without the presents111                kid(None) # A Christmas is a Christmas even without the presents
112        self._prepare_for_next_christmass()112        self._prepare_for_next_christmass()
113113
114    def _prepare_for_next_christmass(self):114    def _prepare_for_next_christmass(self):
115        """Prepare for next Christmas by giving everyone the benefit of the doubt."""115        """Prepare for next Christmas by giving everyone the benefit of the doubt."""
116        self._csi.prepare_for_next_christmass()116        self._csi.prepare_for_next_christmass()
117        self._wishes = OrderedDict()117        self._wishes = OrderedDict()
118118
119119
120class Kid(type):120class Kid(type):
121121
122    @staticmethod122    @staticmethod
123    def _better_init(original_init):123    def _better_init(original_init):
124        """Because sometimes people need a push in the right direction."""124        """Because sometimes people need a push in the right direction."""
125        def decorated(self, *args, **kwargs):125        def decorated(self, *args, **kwargs):
126            original_init(self, *args, **kwargs)126            original_init(self, *args, **kwargs)
127            Person.__init__(self)127            Person.__init__(self)
128        return decorated128        return decorated
129129
130    @staticmethod130    @staticmethod
131    def _better_new(*genetic_information):131    def _better_new(*genetic_information):
132        """Because this is how babies are made, canonically speaking."""132        """Because this is how babies are made, canonically speaking."""
133        return Stork.deliver_baby(genetic_information)133        return Stork.deliver_baby(genetic_information)
134134
135    @staticmethod135    @staticmethod
136    def _better_call(original_call): # Saul136    def _better_call(original_call): # Saul
137        """Add an increase of age to the original call."""137        """Add an increase of age to the original call."""
138        def decorated(self, *args, **kwargs):138        def decorated(self, *args, **kwargs):
139            result = original_call(self, *args, **kwargs)139            result = original_call(self, *args, **kwargs)
140            self.age += 1140            self.age += 1
141            return result141            return result
142        return decorated142        return decorated
143143
144    def __new__(cls, name, bases, attr_dict):144    def __new__(cls, name, bases, attr_dict):
145        """Create a type of kid."""145        """Create a type of kid."""
146        if '__call__' not in attr_dict:146        if '__call__' not in attr_dict:
147            raise NotImplementedError147            raise NotImplementedError
148        attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None))148        attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None))
149        attr_dict['__new__'] = cls._better_new149        attr_dict['__new__'] = cls._better_new
150        attr_dict['__call__'] = cls._better_call(attr_dict['__call__'])150        attr_dict['__call__'] = cls._better_call(attr_dict['__call__'])
151        return super().__new__(cls, name, bases + (Person,), attr_dict)151        return super().__new__(cls, name, bases + (Person,), attr_dict)
152152
153153
154class Person:154class Person:
155    """What is a person?"""155    """What is a person?"""
156156
157    def __init__(self):157    def __init__(self):
n158        """Initialize default attributes for each person.n158        """Initialize age for each person."""
159 
160        Although don't we all start life in love and then slowly
161        fall out of love?
162        """
163        self.age = 0159        self.age = 0
t164        self.in_love = Falset
165160
166    def __hash__(self):161    def __hash__(self):
167        """Can you hash a person?"""162        """Can you hash a person?"""
168        return hash(id(self))163        return hash(id(self))
169164
170165
171class Stork:166class Stork:
172    """A main worker in the baby-delivery service."""167    """A main worker in the baby-delivery service."""
173168
174    _available_storks = []169    _available_storks = []
175170
176    def __init__(self):171    def __init__(self):
177        """Initialize carrying space for babies for the current stork."""172        """Initialize carrying space for babies for the current stork."""
178        self.baby = []173        self.baby = []
179174
180    def _procure_a_baby(self, genetic_information):175    def _procure_a_baby(self, genetic_information):
181        """Where from? No idea."""176        """Where from? No idea."""
182        # Part of an old implementation, left here only for the joke177        # Part of an old implementation, left here only for the joke
183        # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he178        # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he
184        self.baby = [object.__new__(*genetic_information)]179        self.baby = [object.__new__(*genetic_information)]
185        self._____notify_CSI()180        self._____notify_CSI()
186181
187    def _____notify_CSI(self):182    def _____notify_CSI(self):
188        """Nothing to see here, move along,"""183        """Nothing to see here, move along,"""
189        CSI.notify_about_new_baby(self.baby[0])184        CSI.notify_about_new_baby(self.baby[0])
190185
191    def _deliver_baby(self):186    def _deliver_baby(self):
192        """Hehe, *pop*."""187        """Hehe, *pop*."""
193        return self.baby.pop()188        return self.baby.pop()
194189
195    @classmethod190    @classmethod
196    def deliver_baby(cls, genetic_information):191    def deliver_baby(cls, genetic_information):
197        """Deliver a baby to the happy parents."""192        """Deliver a baby to the happy parents."""
198        threading.Thread(target=cls._request_storks).start()193        threading.Thread(target=cls._request_storks).start()
199        while not cls._available_storks:194        while not cls._available_storks:
200            print("There are no storks available, please wait as your call is important to us!")195            print("There are no storks available, please wait as your call is important to us!")
201            time.sleep(0.03)196            time.sleep(0.03)
202        return cls._dispatch_stork(genetic_information)197        return cls._dispatch_stork(genetic_information)
203198
204    @classmethod199    @classmethod
205    def _request_storks(cls):200    def _request_storks(cls):
206        """Request for adding storks to the stork pool."""201        """Request for adding storks to the stork pool."""
207        time.sleep(0.09)202        time.sleep(0.09)
208        storks = [cls() for _ in range(random.randint(1, 10))]203        storks = [cls() for _ in range(random.randint(1, 10))]
209        cls._available_storks.extend(storks)204        cls._available_storks.extend(storks)
210        print("Thank you for your patience. Storks are ready for dispatch!")205        print("Thank you for your patience. Storks are ready for dispatch!")
211206
212    @classmethod207    @classmethod
213    def _dispatch_stork(cls, genetic_information):208    def _dispatch_stork(cls, genetic_information):
214        """Dispatch an available stork in the area."""209        """Dispatch an available stork in the area."""
215        stork_index = random.randint(0, len(cls._available_storks) - 1)210        stork_index = random.randint(0, len(cls._available_storks) - 1)
216        stork = cls._available_storks.pop(stork_index)211        stork = cls._available_storks.pop(stork_index)
217        stork._procure_a_baby(genetic_information)212        stork._procure_a_baby(genetic_information)
218        print("Stork dispatched, please wait for your delivery.")213        print("Stork dispatched, please wait for your delivery.")
219        return stork._deliver_baby()214        return stork._deliver_baby()
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op