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

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

3 точки общо

5 успешни теста
15 неуспешни теста
Код (fix various issues)
Скрий всички коментари

  1# type: ignore
  2
  3from itertools import takewhile, dropwhile
  4from re import search
  5from random import choice
  6from collections import Counter
  7
  8
  9class Singleton(type):
 10
 11    def __new__(cls, name, bases, attr_dict):
 12        cls_instances = {}
 13
 14        def singleton_new(inner_cls):
 15            identity = id(inner_cls)
 16
 17            if identity in cls_instances:
 18                return cls_instances[identity]
 19            else:
 20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)
 21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)
 22                class_instance.iter = 0
 23                class_instance.iter_registry = [{}]
 24                class_instance.kid_registry = {}
 25                cls_instances[identity] = class_instance
 26                return class_instance
 27
 28        attr_dict['__new__'] = singleton_new
 29
 30        singleton_instance = super().__new__(cls, name, bases, attr_dict)
 31
 32        return singleton_instance
 33
 34
 35class Kid(type):
 36    def __new__(cls, name, bases, attr_dict):
 37
 38        if '__call__' not in attr_dict:
 39            raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')
 40
 41        def kidmeta_new(inner_cls):
 42            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)
 43
 44            for prop in takewhile(lambda k: '__call__' in dir(getattr(kid_instance, k)) and not k.startswith('_') and getattr(kid_instance, k).__class__.__name__ == 'method' and getattr(type(kid_instance), k).__class__.__name__ == 'function', dir(kid_instance)):
 45                old_impl = kid_instance[prop]
 46
 47                def new_impl(*args, **kwargs):
 48                    try:
 49                        old_impl(*args, **kwargs)
 50                    except BaseException as exception:
 51                        Santa()._upsert_gift(id(kid_instance), 'coal')
 52                        raise exception
 53
 54                kid_instance[prop] = new_impl
 55
 56            Santa().register_kid(kid_instance)
 57
 58            return kid_instance
 59
 60        attr_dict['__new__'] = kidmeta_new
 61
 62        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)
 63
 64        return kidmeta_instance
 65
 66
 67class Santa(metaclass=Singleton):
 68    @staticmethod
 69    def parse_call_wish(wish):
 70        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
 71
 72    @staticmethod
 73    def parse_letter_wish(wish):
 74        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
 75        kid_id = None
 76
 77        for line in wish.split('\n'):
 78            if res := search(r"^(\d+)$", line.strip()):
 79                kid_id = res.group()
 80                break
 81
 82        return [kid_id, gift]
 83
 84    @property
 85    def current_iter(self):
 86        return self.iter_registry[self.iter]
 87
 88    def __call__(self, kid, wish):
 89        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]
 90
 91        self._upsert_gift(kid_id, gift)
 92
 93    def __matmul__(self, wish):
 94        [kid_id, gift] = self.parse_letter_wish(wish)
 95
 96        self._upsert_gift(kid_id, gift)
 97
 98    def __iter__(self):
 99        current_iter = self.current_iter.values()
100
101        def _iter():
102            yield from current_iter
103
104        return _iter
105
106    def _upsert_gift(self, kid_id, gift):
107        if kid_id in self.current_iter:
108            self.iter_registry[self.iter][kid_id] = gift
109        else:
110            self.iter_registry[self.iter] |= {kid_id: gift}
111
112    def get_gift(self, kid_id):
113        if kid_id in self.current_iter:
114            return self.current_iter[kid_id]
115        else:
116            counter = Counter(self.current_iter.values())
117            max_count = max(counter.values())
118            top_gifts = [k for k in counter if counter[k] == max_count]
119            return choice(top_gifts)
120
121    def xmas(self):
122        for (kid, kid_id) in dropwhile(lambda kid_id: self.kid_registry[kid_id][1] < 5, self.kid_registry):
123            kid(self.get_gift(kid_id))
124
125        self.iter += 1
126
127        for kid_id in self.kid_registry.keys():
128            self.kid_registry[kid_id][1] += 1
129
130    def register_kid(self, kid):
131        self.kid_registry[id(kid)] = [kid, 0]

..EEEEEEF.FFFF..FFEF
======================================================================
ERROR: test_call (test.TestSanta.test_call)
Test sending message via calling.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 56, in test_call
self.assertEqual(list(self.santa), ['toy1', 'toy2'])
^^^^^^^^^^^^^^^^
TypeError: iter() returned non-iterator of type 'function'

======================================================================
ERROR: test_call_and_mail_same_kid (test.TestSanta.test_call_and_mail_same_kid)
Test that calls and mails work for the same kid.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 71, in test_call_and_mail_same_kid
self.assertEqual(list(self.santa), ['toy1'])
^^^^^^^^^^^^^^^^
TypeError: iter() returned non-iterator of type 'function'

======================================================================
ERROR: test_iterable (test.TestSanta.test_iterable)
Ensure Santa can be iterated multiple times including overwriting presents.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 127, in test_iterable
self.santa(kid2, '"something not used"')
File "/tmp/solution.py", line 89, in __call__
[kid_id, gift] = [id(kid), self.parse_call_wish(wish)]
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in parse_call_wish
return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'groups'

======================================================================
ERROR: test_mail (test.TestSanta.test_mail)
Test sending message via email.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 64, in test_mail
self.assertEqual(list(self.santa), ['toy1', 'toy2'])
^^^^^^^^^^^^^^^^
TypeError: iter() returned non-iterator of type 'function'

======================================================================
ERROR: test_present_matching (test.TestSanta.test_present_matching)
Test matching signature in the letter.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 87, in test_present_matching
self.santa @ f"""
File "/tmp/solution.py", line 94, in __matmul__
[kid_id, gift] = self.parse_letter_wish(wish)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 74, in parse_letter_wish
gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'groups'

======================================================================
ERROR: test_santa_gift_order (test.TestSanta.test_santa_gift_order)
Test ordering of the Santa iterator.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 260, in test_santa_gift_order
self.assertEqual(list(self.santa), ["toy2v2", "toy3", "toy1"])
^^^^^^^^^^^^^^^^
TypeError: iter() returned non-iterator of type 'function'

======================================================================
ERROR: test_xmass_years_5_and_over (test.TestSanta.test_xmass_years_5_and_over)
Test with passing years with kid aged 5 and over.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 211, in test_xmass_years_5_and_over
self.santa(kid1, '"toy"')
File "/tmp/solution.py", line 91, in __call__
self._upsert_gift(kid_id, gift)
File "/tmp/solution.py", line 107, in _upsert_gift
if kid_id in self.current_iter:
^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 86, in current_iter
return self.iter_registry[self.iter]
~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
IndexError: list index out of range

======================================================================
FAIL: test_signature_matching (test.TestSanta.test_signature_matching)
Test matching present in the letter / call.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 118, in test_signature_matching
self.assertEqual(kid1.SECRET_PRESENT, 'toy1')
AssertionError: None != 'toy1'

======================================================================
FAIL: test_xmass (test.TestSanta.test_xmass)
Test a simple Christmas case.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 141, in test_xmass
self.assertEqual(kid1.SECRET_PRESENT, 'toy1')
AssertionError: None != 'toy1'

======================================================================
FAIL: test_xmass_kid_with_multiple_wishes (test.TestSanta.test_xmass_kid_with_multiple_wishes)
Test a Christmas with a kid who sends multiple wishes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 187, in test_xmass_kid_with_multiple_wishes
self.assertEqual(kid1.SECRET_PRESENT, 'toy3')
AssertionError: None != 'toy3'

======================================================================
FAIL: test_xmass_kid_without_a_wish (test.TestSanta.test_xmass_kid_without_a_wish)
Test a Christmas with a kids that hasn't sent a wish.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 175, in test_xmass_kid_without_a_wish
self.assertEqual(kid1.SECRET_PRESENT, 'toy1')
AssertionError: None != 'toy1'

======================================================================
FAIL: test_xmass_naughty (test.TestSanta.test_xmass_naughty)
Test a Christmas with naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 227, in test_xmass_naughty
self.assertEqual(kid1.SECRET_PRESENT, 'coal')
AssertionError: None != 'coal'

======================================================================
FAIL: test_xmass_private_with_error (test.TestSanta.test_xmass_private_with_error)
Test a Christmas with not-so-naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 240, in test_xmass_private_with_error
self.assertEqual(kid1.SECRET_PRESENT, 'sirenie')
AssertionError: None != 'sirenie'

======================================================================
FAIL: test_xmass_public_with_no_error (test.TestSanta.test_xmass_public_with_no_error)
Test a Christmas with not-so-naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 248, in test_xmass_public_with_no_error
self.assertEqual(kid1.SECRET_PRESENT, 'sirenie')
AssertionError: None != 'sirenie'

======================================================================
FAIL: test_xmass_years_under_5 (test.TestSanta.test_xmass_years_under_5)
Test with passing years with a kid under 5 years old.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 194, in test_xmass_years_under_5
self.assertEqual(kid1.SECRET_PRESENT, 'toy1')
AssertionError: None != 'toy1'

----------------------------------------------------------------------
Ran 20 tests in 0.058s

FAILED (failures=8, errors=7)

Дискусия
Димитър Фенерски
19.12.2024 18:05

self.iter_registry.append({}) на ред 126 за правилно годишно ресетване липсва
История

f1# type: ignoref1# type: ignore
22
3from itertools import takewhile, dropwhile3from itertools import takewhile, dropwhile
4from re import search4from re import search
5from random import choice5from random import choice
6from collections import Counter6from collections import Counter
77
88
9class Singleton(type):9class Singleton(type):
1010
11    def __new__(cls, name, bases, attr_dict):11    def __new__(cls, name, bases, attr_dict):
12        cls_instances = {}12        cls_instances = {}
1313
14        def singleton_new(inner_cls):14        def singleton_new(inner_cls):
15            identity = id(inner_cls)15            identity = id(inner_cls)
1616
17            if identity in cls_instances:17            if identity in cls_instances:
18                return cls_instances[identity]18                return cls_instances[identity]
19            else:19            else:
20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)
21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)
22                class_instance.iter = 022                class_instance.iter = 0
23                class_instance.iter_registry = [{}]23                class_instance.iter_registry = [{}]
24                class_instance.kid_registry = {}24                class_instance.kid_registry = {}
25                cls_instances[identity] = class_instance25                cls_instances[identity] = class_instance
26                return class_instance26                return class_instance
2727
28        attr_dict['__new__'] = singleton_new28        attr_dict['__new__'] = singleton_new
2929
30        singleton_instance = super().__new__(cls, name, bases, attr_dict)30        singleton_instance = super().__new__(cls, name, bases, attr_dict)
3131
32        return singleton_instance32        return singleton_instance
3333
3434
35class Kid(type):35class Kid(type):
36    def __new__(cls, name, bases, attr_dict):36    def __new__(cls, name, bases, attr_dict):
3737
38        if '__call__' not in attr_dict:38        if '__call__' not in attr_dict:
39            raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')39            raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')
4040
41        def kidmeta_new(inner_cls):41        def kidmeta_new(inner_cls):
42            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)42            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)
4343
44            for prop in takewhile(lambda k: '__call__' in dir(getattr(kid_instance, k)) and not k.startswith('_') and getattr(kid_instance, k).__class__.__name__ == 'method' and getattr(type(kid_instance), k).__class__.__name__ == 'function', dir(kid_instance)):44            for prop in takewhile(lambda k: '__call__' in dir(getattr(kid_instance, k)) and not k.startswith('_') and getattr(kid_instance, k).__class__.__name__ == 'method' and getattr(type(kid_instance), k).__class__.__name__ == 'function', dir(kid_instance)):
45                old_impl = kid_instance[prop]45                old_impl = kid_instance[prop]
4646
47                def new_impl(*args, **kwargs):47                def new_impl(*args, **kwargs):
48                    try:48                    try:
49                        old_impl(*args, **kwargs)49                        old_impl(*args, **kwargs)
50                    except BaseException as exception:50                    except BaseException as exception:
51                        Santa()._upsert_gift(id(kid_instance), 'coal')51                        Santa()._upsert_gift(id(kid_instance), 'coal')
52                        raise exception52                        raise exception
5353
54                kid_instance[prop] = new_impl54                kid_instance[prop] = new_impl
5555
56            Santa().register_kid(kid_instance)56            Santa().register_kid(kid_instance)
5757
58            return kid_instance58            return kid_instance
5959
60        attr_dict['__new__'] = kidmeta_new60        attr_dict['__new__'] = kidmeta_new
6161
62        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)62        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)
6363
64        return kidmeta_instance64        return kidmeta_instance
6565
6666
67class Santa(metaclass=Singleton):67class Santa(metaclass=Singleton):
68    @staticmethod68    @staticmethod
69    def parse_call_wish(wish):69    def parse_call_wish(wish):
70        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]70        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
7171
72    @staticmethod72    @staticmethod
73    def parse_letter_wish(wish):73    def parse_letter_wish(wish):
74        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]74        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
75        kid_id = None75        kid_id = None
7676
77        for line in wish.split('\n'):77        for line in wish.split('\n'):
78            if res := search(r"^(\d+)$", line.strip()):78            if res := search(r"^(\d+)$", line.strip()):
79                kid_id = res.group()79                kid_id = res.group()
80                break80                break
8181
82        return [kid_id, gift]82        return [kid_id, gift]
8383
84    @property84    @property
85    def current_iter(self):85    def current_iter(self):
86        return self.iter_registry[self.iter]86        return self.iter_registry[self.iter]
8787
88    def __call__(self, kid, wish):88    def __call__(self, kid, wish):
89        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]89        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]
9090
91        self._upsert_gift(kid_id, gift)91        self._upsert_gift(kid_id, gift)
9292
93    def __matmul__(self, wish):93    def __matmul__(self, wish):
94        [kid_id, gift] = self.parse_letter_wish(wish)94        [kid_id, gift] = self.parse_letter_wish(wish)
9595
96        self._upsert_gift(kid_id, gift)96        self._upsert_gift(kid_id, gift)
9797
98    def __iter__(self):98    def __iter__(self):
99        current_iter = self.current_iter.values()99        current_iter = self.current_iter.values()
100100
101        def _iter():101        def _iter():
102            yield from current_iter102            yield from current_iter
103103
104        return _iter104        return _iter
105105
106    def _upsert_gift(self, kid_id, gift):106    def _upsert_gift(self, kid_id, gift):
107        if kid_id in self.current_iter:107        if kid_id in self.current_iter:
n108            self.current_iter[kid_id] = giftn108            self.iter_registry[self.iter][kid_id] = gift
109        else:109        else:
110            self.iter_registry[self.iter] |= {kid_id: gift}110            self.iter_registry[self.iter] |= {kid_id: gift}
111111
112    def get_gift(self, kid_id):112    def get_gift(self, kid_id):
113        if kid_id in self.current_iter:113        if kid_id in self.current_iter:
114            return self.current_iter[kid_id]114            return self.current_iter[kid_id]
115        else:115        else:
116            counter = Counter(self.current_iter.values())116            counter = Counter(self.current_iter.values())
117            max_count = max(counter.values())117            max_count = max(counter.values())
118            top_gifts = [k for k in counter if counter[k] == max_count]118            top_gifts = [k for k in counter if counter[k] == max_count]
119            return choice(top_gifts)119            return choice(top_gifts)
120120
121    def xmas(self):121    def xmas(self):
n122        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):n122        for (kid, kid_id) in dropwhile(lambda kid_id: self.kid_registry[kid_id][1] < 5, self.kid_registry):
123            kid(self.get_gift(kid_id))123            kid(self.get_gift(kid_id))
124124
125        self.iter += 1125        self.iter += 1
126126
127        for kid_id in self.kid_registry.keys():127        for kid_id in self.kid_registry.keys():
128            self.kid_registry[kid_id][1] += 1128            self.kid_registry[kid_id][1] += 1
129129
130    def register_kid(self, kid):130    def register_kid(self, kid):
t131        self.kid_registry[id(kid)] = (kid, 0)t131        self.kid_registry[id(kid)] = [kid, 0]
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1# type: ignoref1# type: ignore
22
3from itertools import takewhile, dropwhile3from itertools import takewhile, dropwhile
4from re import search4from re import search
5from random import choice5from random import choice
6from collections import Counter6from collections import Counter
77
88
9class Singleton(type):9class Singleton(type):
1010
11    def __new__(cls, name, bases, attr_dict):11    def __new__(cls, name, bases, attr_dict):
12        cls_instances = {}12        cls_instances = {}
1313
14        def singleton_new(inner_cls):14        def singleton_new(inner_cls):
15            identity = id(inner_cls)15            identity = id(inner_cls)
1616
17            if identity in cls_instances:17            if identity in cls_instances:
18                return cls_instances[identity]18                return cls_instances[identity]
19            else:19            else:
20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)
21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)
nn22                class_instance.iter = 0
23                class_instance.iter_registry = [{}]
24                class_instance.kid_registry = {}
22                cls_instances[identity] = class_instance25                cls_instances[identity] = class_instance
23                return class_instance26                return class_instance
2427
25        attr_dict['__new__'] = singleton_new28        attr_dict['__new__'] = singleton_new
2629
27        singleton_instance = super().__new__(cls, name, bases, attr_dict)30        singleton_instance = super().__new__(cls, name, bases, attr_dict)
2831
29        return singleton_instance32        return singleton_instance
3033
3134
32class Kid(type):35class Kid(type):
33    def __new__(cls, name, bases, attr_dict):36    def __new__(cls, name, bases, attr_dict):
3437
35        if '__call__' not in attr_dict:38        if '__call__' not in attr_dict:
36            raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')39            raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')
3740
38        def kidmeta_new(inner_cls):41        def kidmeta_new(inner_cls):
39            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)42            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)
4043
41            for prop in takewhile(lambda k: '__call__' in dir(getattr(kid_instance, k)) and not k.startswith('_') and getattr(kid_instance, k).__class__.__name__ == 'method' and getattr(type(kid_instance), k).__class__.__name__ == 'function', dir(kid_instance)):44            for prop in takewhile(lambda k: '__call__' in dir(getattr(kid_instance, k)) and not k.startswith('_') and getattr(kid_instance, k).__class__.__name__ == 'method' and getattr(type(kid_instance), k).__class__.__name__ == 'function', dir(kid_instance)):
42                old_impl = kid_instance[prop]45                old_impl = kid_instance[prop]
4346
44                def new_impl(*args, **kwargs):47                def new_impl(*args, **kwargs):
45                    try:48                    try:
46                        old_impl(*args, **kwargs)49                        old_impl(*args, **kwargs)
47                    except BaseException as exception:50                    except BaseException as exception:
48                        Santa()._upsert_gift(id(kid_instance), 'coal')51                        Santa()._upsert_gift(id(kid_instance), 'coal')
49                        raise exception52                        raise exception
5053
51                kid_instance[prop] = new_impl54                kid_instance[prop] = new_impl
5255
53            Santa().register_kid(kid_instance)56            Santa().register_kid(kid_instance)
5457
55            return kid_instance58            return kid_instance
5659
57        attr_dict['__new__'] = kidmeta_new60        attr_dict['__new__'] = kidmeta_new
5861
59        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)62        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)
6063
61        return kidmeta_instance64        return kidmeta_instance
6265
6366
64class Santa(metaclass=Singleton):67class Santa(metaclass=Singleton):
65    @staticmethod68    @staticmethod
66    def parse_call_wish(wish):69    def parse_call_wish(wish):
67        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]70        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
6871
69    @staticmethod72    @staticmethod
70    def parse_letter_wish(wish):73    def parse_letter_wish(wish):
71        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]74        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
72        kid_id = None75        kid_id = None
7376
74        for line in wish.split('\n'):77        for line in wish.split('\n'):
75            if res := search(r"^(\d+)$", line.strip()):78            if res := search(r"^(\d+)$", line.strip()):
76                kid_id = res.group()79                kid_id = res.group()
77                break80                break
7881
79        return [kid_id, gift]82        return [kid_id, gift]
8083
81    @property84    @property
82    def current_iter(self):85    def current_iter(self):
83        return self.iter_registry[self.iter]86        return self.iter_registry[self.iter]
8487
t85    def __init__(self):t
86        self.iter = 0
87        self.iter_registry = [{}]
88        self.kid_registry = {}
89 
90    def __call__(self, kid, wish):88    def __call__(self, kid, wish):
91        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]89        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]
9290
93        self._upsert_gift(kid_id, gift)91        self._upsert_gift(kid_id, gift)
9492
95    def __matmul__(self, wish):93    def __matmul__(self, wish):
96        [kid_id, gift] = self.parse_letter_wish(wish)94        [kid_id, gift] = self.parse_letter_wish(wish)
9795
98        self._upsert_gift(kid_id, gift)96        self._upsert_gift(kid_id, gift)
9997
100    def __iter__(self):98    def __iter__(self):
101        current_iter = self.current_iter.values()99        current_iter = self.current_iter.values()
102100
103        def _iter():101        def _iter():
104            yield from current_iter102            yield from current_iter
105103
106        return _iter104        return _iter
107105
108    def _upsert_gift(self, kid_id, gift):106    def _upsert_gift(self, kid_id, gift):
109        if kid_id in self.current_iter:107        if kid_id in self.current_iter:
110            self.current_iter[kid_id] = gift108            self.current_iter[kid_id] = gift
111        else:109        else:
112            self.iter_registry[self.iter] |= {kid_id: gift}110            self.iter_registry[self.iter] |= {kid_id: gift}
113111
114    def get_gift(self, kid_id):112    def get_gift(self, kid_id):
115        if kid_id in self.current_iter:113        if kid_id in self.current_iter:
116            return self.current_iter[kid_id]114            return self.current_iter[kid_id]
117        else:115        else:
118            counter = Counter(self.current_iter.values())116            counter = Counter(self.current_iter.values())
119            max_count = max(counter.values())117            max_count = max(counter.values())
120            top_gifts = [k for k in counter if counter[k] == max_count]118            top_gifts = [k for k in counter if counter[k] == max_count]
121            return choice(top_gifts)119            return choice(top_gifts)
122120
123    def xmas(self):121    def xmas(self):
124        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):122        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):
125            kid(self.get_gift(kid_id))123            kid(self.get_gift(kid_id))
126124
127        self.iter += 1125        self.iter += 1
128126
129        for kid_id in self.kid_registry.keys():127        for kid_id in self.kid_registry.keys():
130            self.kid_registry[kid_id][1] += 1128            self.kid_registry[kid_id][1] += 1
131129
132    def register_kid(self, kid):130    def register_kid(self, kid):
133        self.kid_registry[id(kid)] = (kid, 0)131        self.kid_registry[id(kid)] = (kid, 0)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1# type: ignoref1# type: ignore
22
3from itertools import takewhile, dropwhile3from itertools import takewhile, dropwhile
4from re import search4from re import search
5from random import choice5from random import choice
6from collections import Counter6from collections import Counter
77
88
9class Singleton(type):9class Singleton(type):
1010
11    def __new__(cls, name, bases, attr_dict):11    def __new__(cls, name, bases, attr_dict):
12        cls_instances = {}12        cls_instances = {}
1313
14        def singleton_new(inner_cls):14        def singleton_new(inner_cls):
15            identity = id(inner_cls)15            identity = id(inner_cls)
1616
17            if identity in cls_instances:17            if identity in cls_instances:
18                return cls_instances[identity]18                return cls_instances[identity]
19            else:19            else:
20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)
21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)
22                cls_instances[identity] = class_instance22                cls_instances[identity] = class_instance
23                return class_instance23                return class_instance
2424
25        attr_dict['__new__'] = singleton_new25        attr_dict['__new__'] = singleton_new
2626
27        singleton_instance = super().__new__(cls, name, bases, attr_dict)27        singleton_instance = super().__new__(cls, name, bases, attr_dict)
2828
29        return singleton_instance29        return singleton_instance
3030
3131
32class Kid(type):32class Kid(type):
33    def __new__(cls, name, bases, attr_dict):33    def __new__(cls, name, bases, attr_dict):
3434
35        if '__call__' not in attr_dict:35        if '__call__' not in attr_dict:
36            raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')36            raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')
3737
38        def kidmeta_new(inner_cls):38        def kidmeta_new(inner_cls):
39            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)39            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)
4040
t41            for prop in takewhile(lambda k: '__call__' in dir(kid_instance[k]) and not k.startswith('_') and kid_instance[k].__class__.__name__ == 'method' and type(kid_instance)[k].__class__.__name__ == 'function', dir(kid_instance)):t41            for prop in takewhile(lambda k: '__call__' in dir(getattr(kid_instance, k)) and not k.startswith('_') and getattr(kid_instance, k).__class__.__name__ == 'method' and getattr(type(kid_instance), k).__class__.__name__ == 'function', dir(kid_instance)):
42                old_impl = kid_instance[prop]42                old_impl = kid_instance[prop]
4343
44                def new_impl(*args, **kwargs):44                def new_impl(*args, **kwargs):
45                    try:45                    try:
46                        old_impl(*args, **kwargs)46                        old_impl(*args, **kwargs)
47                    except BaseException as exception:47                    except BaseException as exception:
48                        Santa()._upsert_gift(id(kid_instance), 'coal')48                        Santa()._upsert_gift(id(kid_instance), 'coal')
49                        raise exception49                        raise exception
5050
51                kid_instance[prop] = new_impl51                kid_instance[prop] = new_impl
5252
53            Santa().register_kid(kid_instance)53            Santa().register_kid(kid_instance)
5454
55            return kid_instance55            return kid_instance
5656
57        attr_dict['__new__'] = kidmeta_new57        attr_dict['__new__'] = kidmeta_new
5858
59        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)59        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)
6060
61        return kidmeta_instance61        return kidmeta_instance
6262
6363
64class Santa(metaclass=Singleton):64class Santa(metaclass=Singleton):
65    @staticmethod65    @staticmethod
66    def parse_call_wish(wish):66    def parse_call_wish(wish):
67        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]67        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
6868
69    @staticmethod69    @staticmethod
70    def parse_letter_wish(wish):70    def parse_letter_wish(wish):
71        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]71        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
72        kid_id = None72        kid_id = None
7373
74        for line in wish.split('\n'):74        for line in wish.split('\n'):
75            if res := search(r"^(\d+)$", line.strip()):75            if res := search(r"^(\d+)$", line.strip()):
76                kid_id = res.group()76                kid_id = res.group()
77                break77                break
7878
79        return [kid_id, gift]79        return [kid_id, gift]
8080
81    @property81    @property
82    def current_iter(self):82    def current_iter(self):
83        return self.iter_registry[self.iter]83        return self.iter_registry[self.iter]
8484
85    def __init__(self):85    def __init__(self):
86        self.iter = 086        self.iter = 0
87        self.iter_registry = [{}]87        self.iter_registry = [{}]
88        self.kid_registry = {}88        self.kid_registry = {}
8989
90    def __call__(self, kid, wish):90    def __call__(self, kid, wish):
91        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]91        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]
9292
93        self._upsert_gift(kid_id, gift)93        self._upsert_gift(kid_id, gift)
9494
95    def __matmul__(self, wish):95    def __matmul__(self, wish):
96        [kid_id, gift] = self.parse_letter_wish(wish)96        [kid_id, gift] = self.parse_letter_wish(wish)
9797
98        self._upsert_gift(kid_id, gift)98        self._upsert_gift(kid_id, gift)
9999
100    def __iter__(self):100    def __iter__(self):
101        current_iter = self.current_iter.values()101        current_iter = self.current_iter.values()
102102
103        def _iter():103        def _iter():
104            yield from current_iter104            yield from current_iter
105105
106        return _iter106        return _iter
107107
108    def _upsert_gift(self, kid_id, gift):108    def _upsert_gift(self, kid_id, gift):
109        if kid_id in self.current_iter:109        if kid_id in self.current_iter:
110            self.current_iter[kid_id] = gift110            self.current_iter[kid_id] = gift
111        else:111        else:
112            self.iter_registry[self.iter] |= {kid_id: gift}112            self.iter_registry[self.iter] |= {kid_id: gift}
113113
114    def get_gift(self, kid_id):114    def get_gift(self, kid_id):
115        if kid_id in self.current_iter:115        if kid_id in self.current_iter:
116            return self.current_iter[kid_id]116            return self.current_iter[kid_id]
117        else:117        else:
118            counter = Counter(self.current_iter.values())118            counter = Counter(self.current_iter.values())
119            max_count = max(counter.values())119            max_count = max(counter.values())
120            top_gifts = [k for k in counter if counter[k] == max_count]120            top_gifts = [k for k in counter if counter[k] == max_count]
121            return choice(top_gifts)121            return choice(top_gifts)
122122
123    def xmas(self):123    def xmas(self):
124        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):124        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):
125            kid(self.get_gift(kid_id))125            kid(self.get_gift(kid_id))
126126
127        self.iter += 1127        self.iter += 1
128128
129        for kid_id in self.kid_registry.keys():129        for kid_id in self.kid_registry.keys():
130            self.kid_registry[kid_id][1] += 1130            self.kid_registry[kid_id][1] += 1
131131
132    def register_kid(self, kid):132    def register_kid(self, kid):
133        self.kid_registry[id(kid)] = (kid, 0)133        self.kid_registry[id(kid)] = (kid, 0)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1# type: ignoref1# type: ignore
22
3from itertools import takewhile, dropwhile3from itertools import takewhile, dropwhile
4from re import search4from re import search
5from random import choice5from random import choice
6from collections import Counter6from collections import Counter
77
88
9class Singleton(type):9class Singleton(type):
1010
11    def __new__(cls, name, bases, attr_dict):11    def __new__(cls, name, bases, attr_dict):
12        cls_instances = {}12        cls_instances = {}
1313
14        def singleton_new(inner_cls):14        def singleton_new(inner_cls):
15            identity = id(inner_cls)15            identity = id(inner_cls)
1616
17            if identity in cls_instances:17            if identity in cls_instances:
18                return cls_instances[identity]18                return cls_instances[identity]
19            else:19            else:
20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)
21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)
22                cls_instances[identity] = class_instance22                cls_instances[identity] = class_instance
23                return class_instance23                return class_instance
2424
25        attr_dict['__new__'] = singleton_new25        attr_dict['__new__'] = singleton_new
2626
27        singleton_instance = super().__new__(cls, name, bases, attr_dict)27        singleton_instance = super().__new__(cls, name, bases, attr_dict)
2828
29        return singleton_instance29        return singleton_instance
3030
3131
32class Kid(type):32class Kid(type):
33    def __new__(cls, name, bases, attr_dict):33    def __new__(cls, name, bases, attr_dict):
3434
nn35        if '__call__' not in attr_dict:
36            raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')
37 
35        def kidmeta_new(inner_cls):38        def kidmeta_new(inner_cls):
36            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)39            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)
3740
38            for prop in takewhile(lambda k: '__call__' in dir(kid_instance[k]) and not k.startswith('_') and kid_instance[k].__class__.__name__ == 'method' and type(kid_instance)[k].__class__.__name__ == 'function', dir(kid_instance)):41            for prop in takewhile(lambda k: '__call__' in dir(kid_instance[k]) and not k.startswith('_') and kid_instance[k].__class__.__name__ == 'method' and type(kid_instance)[k].__class__.__name__ == 'function', dir(kid_instance)):
39                old_impl = kid_instance[prop]42                old_impl = kid_instance[prop]
4043
41                def new_impl(*args, **kwargs):44                def new_impl(*args, **kwargs):
42                    try:45                    try:
43                        old_impl(*args, **kwargs)46                        old_impl(*args, **kwargs)
44                    except BaseException as exception:47                    except BaseException as exception:
45                        Santa()._upsert_gift(id(kid_instance), 'coal')48                        Santa()._upsert_gift(id(kid_instance), 'coal')
46                        raise exception49                        raise exception
4750
48                kid_instance[prop] = new_impl51                kid_instance[prop] = new_impl
4952
t50            if '__call__' not in kid_instance:t
51                raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')
52            else:
53                Santa().register_kid(kid_instance)53            Santa().register_kid(kid_instance)
5454
55            return kid_instance55            return kid_instance
5656
57        attr_dict['__new__'] = kidmeta_new57        attr_dict['__new__'] = kidmeta_new
5858
59        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)59        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)
6060
61        return kidmeta_instance61        return kidmeta_instance
6262
6363
64class Santa(metaclass=Singleton):64class Santa(metaclass=Singleton):
65    @staticmethod65    @staticmethod
66    def parse_call_wish(wish):66    def parse_call_wish(wish):
67        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]67        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
6868
69    @staticmethod69    @staticmethod
70    def parse_letter_wish(wish):70    def parse_letter_wish(wish):
71        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]71        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
72        kid_id = None72        kid_id = None
7373
74        for line in wish.split('\n'):74        for line in wish.split('\n'):
75            if res := search(r"^(\d+)$", line.strip()):75            if res := search(r"^(\d+)$", line.strip()):
76                kid_id = res.group()76                kid_id = res.group()
77                break77                break
7878
79        return [kid_id, gift]79        return [kid_id, gift]
8080
81    @property81    @property
82    def current_iter(self):82    def current_iter(self):
83        return self.iter_registry[self.iter]83        return self.iter_registry[self.iter]
8484
85    def __init__(self):85    def __init__(self):
86        self.iter = 086        self.iter = 0
87        self.iter_registry = [{}]87        self.iter_registry = [{}]
88        self.kid_registry = {}88        self.kid_registry = {}
8989
90    def __call__(self, kid, wish):90    def __call__(self, kid, wish):
91        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]91        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]
9292
93        self._upsert_gift(kid_id, gift)93        self._upsert_gift(kid_id, gift)
9494
95    def __matmul__(self, wish):95    def __matmul__(self, wish):
96        [kid_id, gift] = self.parse_letter_wish(wish)96        [kid_id, gift] = self.parse_letter_wish(wish)
9797
98        self._upsert_gift(kid_id, gift)98        self._upsert_gift(kid_id, gift)
9999
100    def __iter__(self):100    def __iter__(self):
101        current_iter = self.current_iter.values()101        current_iter = self.current_iter.values()
102102
103        def _iter():103        def _iter():
104            yield from current_iter104            yield from current_iter
105105
106        return _iter106        return _iter
107107
108    def _upsert_gift(self, kid_id, gift):108    def _upsert_gift(self, kid_id, gift):
109        if kid_id in self.current_iter:109        if kid_id in self.current_iter:
110            self.current_iter[kid_id] = gift110            self.current_iter[kid_id] = gift
111        else:111        else:
112            self.iter_registry[self.iter] |= {kid_id: gift}112            self.iter_registry[self.iter] |= {kid_id: gift}
113113
114    def get_gift(self, kid_id):114    def get_gift(self, kid_id):
115        if kid_id in self.current_iter:115        if kid_id in self.current_iter:
116            return self.current_iter[kid_id]116            return self.current_iter[kid_id]
117        else:117        else:
118            counter = Counter(self.current_iter.values())118            counter = Counter(self.current_iter.values())
119            max_count = max(counter.values())119            max_count = max(counter.values())
120            top_gifts = [k for k in counter if counter[k] == max_count]120            top_gifts = [k for k in counter if counter[k] == max_count]
121            return choice(top_gifts)121            return choice(top_gifts)
122122
123    def xmas(self):123    def xmas(self):
124        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):124        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):
125            kid(self.get_gift(kid_id))125            kid(self.get_gift(kid_id))
126126
127        self.iter += 1127        self.iter += 1
128128
129        for kid_id in self.kid_registry.keys():129        for kid_id in self.kid_registry.keys():
130            self.kid_registry[kid_id][1] += 1130            self.kid_registry[kid_id][1] += 1
131131
132    def register_kid(self, kid):132    def register_kid(self, kid):
133        self.kid_registry[id(kid)] = (kid, 0)133        self.kid_registry[id(kid)] = (kid, 0)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1# type: ignoref1# type: ignore
22
3from itertools import takewhile, dropwhile3from itertools import takewhile, dropwhile
4from re import search4from re import search
5from random import choice5from random import choice
6from collections import Counter6from collections import Counter
77
88
9class Singleton(type):9class Singleton(type):
1010
11    def __new__(cls, name, bases, attr_dict):11    def __new__(cls, name, bases, attr_dict):
12        cls_instances = {}12        cls_instances = {}
1313
14        def singleton_new(inner_cls):14        def singleton_new(inner_cls):
15            identity = id(inner_cls)15            identity = id(inner_cls)
1616
17            if identity in cls_instances:17            if identity in cls_instances:
18                return cls_instances[identity]18                return cls_instances[identity]
19            else:19            else:
20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)20                # The parent class of the class `inner_cls` (1st argument) by traversing the `__mro__` of `inner_cls` (2nd argument)
21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)21                class_instance = super(inner_cls, inner_cls).__new__(inner_cls)
22                cls_instances[identity] = class_instance22                cls_instances[identity] = class_instance
23                return class_instance23                return class_instance
2424
25        attr_dict['__new__'] = singleton_new25        attr_dict['__new__'] = singleton_new
2626
27        singleton_instance = super().__new__(cls, name, bases, attr_dict)27        singleton_instance = super().__new__(cls, name, bases, attr_dict)
2828
29        return singleton_instance29        return singleton_instance
3030
3131
32class Kid(type):32class Kid(type):
33    def __new__(cls, name, bases, attr_dict):33    def __new__(cls, name, bases, attr_dict):
3434
35        def kidmeta_new(inner_cls):35        def kidmeta_new(inner_cls):
36            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)36            kid_instance = super(inner_cls, inner_cls).__new__(inner_cls)
3737
38            for prop in takewhile(lambda k: '__call__' in dir(kid_instance[k]) and not k.startswith('_') and kid_instance[k].__class__.__name__ == 'method' and type(kid_instance)[k].__class__.__name__ == 'function', dir(kid_instance)):38            for prop in takewhile(lambda k: '__call__' in dir(kid_instance[k]) and not k.startswith('_') and kid_instance[k].__class__.__name__ == 'method' and type(kid_instance)[k].__class__.__name__ == 'function', dir(kid_instance)):
39                old_impl = kid_instance[prop]39                old_impl = kid_instance[prop]
4040
41                def new_impl(*args, **kwargs):41                def new_impl(*args, **kwargs):
42                    try:42                    try:
43                        old_impl(*args, **kwargs)43                        old_impl(*args, **kwargs)
44                    except BaseException as exception:44                    except BaseException as exception:
45                        Santa()._upsert_gift(id(kid_instance), 'coal')45                        Santa()._upsert_gift(id(kid_instance), 'coal')
46                        raise exception46                        raise exception
4747
48                kid_instance[prop] = new_impl48                kid_instance[prop] = new_impl
4949
50            if '__call__' not in kid_instance:50            if '__call__' not in kid_instance:
51                raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')51                raise NotImplementedError('bound/unbound + mro + super + metaclasses :))))))))))))))))))')
52            else:52            else:
53                Santa().register_kid(kid_instance)53                Santa().register_kid(kid_instance)
5454
55            return kid_instance55            return kid_instance
5656
57        attr_dict['__new__'] = kidmeta_new57        attr_dict['__new__'] = kidmeta_new
5858
59        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)59        kidmeta_instance = super().__new__(cls, name, bases, attr_dict)
6060
61        return kidmeta_instance61        return kidmeta_instance
6262
6363
64class Santa(metaclass=Singleton):64class Santa(metaclass=Singleton):
65    @staticmethod65    @staticmethod
66    def parse_call_wish(wish):66    def parse_call_wish(wish):
67        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]67        return search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
6868
69    @staticmethod69    @staticmethod
70    def parse_letter_wish(wish):70    def parse_letter_wish(wish):
71        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]71        gift = search(r"(['\"]{1})([a-zA-Z0-9]+)(['\"]{1})", wish).groups()[1]
72        kid_id = None72        kid_id = None
7373
74        for line in wish.split('\n'):74        for line in wish.split('\n'):
75            if res := search(r"^(\d+)$", line.strip()):75            if res := search(r"^(\d+)$", line.strip()):
76                kid_id = res.group()76                kid_id = res.group()
77                break77                break
7878
79        return [kid_id, gift]79        return [kid_id, gift]
8080
81    @property81    @property
82    def current_iter(self):82    def current_iter(self):
83        return self.iter_registry[self.iter]83        return self.iter_registry[self.iter]
8484
85    def __init__(self):85    def __init__(self):
86        self.iter = 086        self.iter = 0
87        self.iter_registry = [{}]87        self.iter_registry = [{}]
88        self.kid_registry = {}88        self.kid_registry = {}
8989
90    def __call__(self, kid, wish):90    def __call__(self, kid, wish):
91        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]91        [kid_id, gift] = [id(kid), self.parse_call_wish(wish)]
9292
93        self._upsert_gift(kid_id, gift)93        self._upsert_gift(kid_id, gift)
9494
95    def __matmul__(self, wish):95    def __matmul__(self, wish):
96        [kid_id, gift] = self.parse_letter_wish(wish)96        [kid_id, gift] = self.parse_letter_wish(wish)
9797
98        self._upsert_gift(kid_id, gift)98        self._upsert_gift(kid_id, gift)
9999
100    def __iter__(self):100    def __iter__(self):
101        current_iter = self.current_iter.values()101        current_iter = self.current_iter.values()
102102
103        def _iter():103        def _iter():
104            yield from current_iter104            yield from current_iter
105105
106        return _iter106        return _iter
107107
108    def _upsert_gift(self, kid_id, gift):108    def _upsert_gift(self, kid_id, gift):
109        if kid_id in self.current_iter:109        if kid_id in self.current_iter:
110            self.current_iter[kid_id] = gift110            self.current_iter[kid_id] = gift
111        else:111        else:
112            self.iter_registry[self.iter] |= {kid_id: gift}112            self.iter_registry[self.iter] |= {kid_id: gift}
113113
114    def get_gift(self, kid_id):114    def get_gift(self, kid_id):
115        if kid_id in self.current_iter:115        if kid_id in self.current_iter:
116            return self.current_iter[kid_id]116            return self.current_iter[kid_id]
117        else:117        else:
118            counter = Counter(self.current_iter.values())118            counter = Counter(self.current_iter.values())
119            max_count = max(counter.values())119            max_count = max(counter.values())
120            top_gifts = [k for k in counter if counter[k] == max_count]120            top_gifts = [k for k in counter if counter[k] == max_count]
121            return choice(top_gifts)121            return choice(top_gifts)
122122
123    def xmas(self):123    def xmas(self):
124        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):124        for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry):
125            kid(self.get_gift(kid_id))125            kid(self.get_gift(kid_id))
126126
127        self.iter += 1127        self.iter += 1
128128
129        for kid_id in self.kid_registry.keys():129        for kid_id in self.kid_registry.keys():
130            self.kid_registry[kid_id][1] += 1130            self.kid_registry[kid_id][1] += 1
131131
132    def register_kid(self, kid):132    def register_kid(self, kid):
133        self.kid_registry[id(kid)] = (kid, 0)133        self.kid_registry[id(kid)] = (kid, 0)
t134 t
135 
136# santa1 = Santa()
137# santa2 = Santa()
138 
139# print(f"santa 1 is santa2: {santa1 is santa2}")
140 
141 
142class Random():
143    @staticmethod
144    def sm():
145        return 1
146 
147    @classmethod
148    def cm():
149        return 1
150 
151    @property
152    def dynprop(self):
153        return self.x
154 
155    y = 100
156 
157    def __init__(self):
158        self.x = 5
159 
160    def _privatem():
161        return 1
162 
163    def publicm():
164        return 1
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op