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:05self.iter_registry.append({}) на ред 126 за правилно годишно ресетване липсва
|
f | 1 | # type: ignore | f | 1 | # type: ignore |
2 | 2 | ||||
3 | from itertools import takewhile, dropwhile | 3 | from itertools import takewhile, dropwhile | ||
4 | from re import search | 4 | from re import search | ||
5 | from random import choice | 5 | from random import choice | ||
6 | from collections import Counter | 6 | from collections import Counter | ||
7 | 7 | ||||
8 | 8 | ||||
9 | class Singleton(type): | 9 | class Singleton(type): | ||
10 | 10 | ||||
11 | def __new__(cls, name, bases, attr_dict): | 11 | def __new__(cls, name, bases, attr_dict): | ||
12 | cls_instances = {} | 12 | cls_instances = {} | ||
13 | 13 | ||||
14 | def singleton_new(inner_cls): | 14 | def singleton_new(inner_cls): | ||
15 | identity = id(inner_cls) | 15 | identity = id(inner_cls) | ||
16 | 16 | ||||
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 = 0 | 22 | 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_instance | 25 | cls_instances[identity] = class_instance | ||
26 | return class_instance | 26 | return class_instance | ||
27 | 27 | ||||
28 | attr_dict['__new__'] = singleton_new | 28 | attr_dict['__new__'] = singleton_new | ||
29 | 29 | ||||
30 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | 30 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | ||
31 | 31 | ||||
32 | return singleton_instance | 32 | return singleton_instance | ||
33 | 33 | ||||
34 | 34 | ||||
35 | class Kid(type): | 35 | class Kid(type): | ||
36 | def __new__(cls, name, bases, attr_dict): | 36 | def __new__(cls, name, bases, attr_dict): | ||
37 | 37 | ||||
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 :))))))))))))))))))') | ||
40 | 40 | ||||
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) | ||
43 | 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)): | 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] | ||
46 | 46 | ||||
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 exception | 52 | raise exception | ||
53 | 53 | ||||
54 | kid_instance[prop] = new_impl | 54 | kid_instance[prop] = new_impl | ||
55 | 55 | ||||
56 | Santa().register_kid(kid_instance) | 56 | Santa().register_kid(kid_instance) | ||
57 | 57 | ||||
58 | return kid_instance | 58 | return kid_instance | ||
59 | 59 | ||||
60 | attr_dict['__new__'] = kidmeta_new | 60 | attr_dict['__new__'] = kidmeta_new | ||
61 | 61 | ||||
62 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | 62 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | ||
63 | 63 | ||||
64 | return kidmeta_instance | 64 | return kidmeta_instance | ||
65 | 65 | ||||
66 | 66 | ||||
67 | class Santa(metaclass=Singleton): | 67 | class Santa(metaclass=Singleton): | ||
68 | @staticmethod | 68 | @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] | ||
71 | 71 | ||||
72 | @staticmethod | 72 | @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 = None | 75 | kid_id = None | ||
76 | 76 | ||||
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 | break | 80 | break | ||
81 | 81 | ||||
82 | return [kid_id, gift] | 82 | return [kid_id, gift] | ||
83 | 83 | ||||
84 | @property | 84 | @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] | ||
87 | 87 | ||||
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)] | ||
90 | 90 | ||||
91 | self._upsert_gift(kid_id, gift) | 91 | self._upsert_gift(kid_id, gift) | ||
92 | 92 | ||||
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) | ||
95 | 95 | ||||
96 | self._upsert_gift(kid_id, gift) | 96 | self._upsert_gift(kid_id, gift) | ||
97 | 97 | ||||
98 | def __iter__(self): | 98 | def __iter__(self): | ||
99 | current_iter = self.current_iter.values() | 99 | current_iter = self.current_iter.values() | ||
100 | 100 | ||||
101 | def _iter(): | 101 | def _iter(): | ||
102 | yield from current_iter | 102 | yield from current_iter | ||
103 | 103 | ||||
104 | return _iter | 104 | return _iter | ||
105 | 105 | ||||
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: | ||
n | 108 | self.current_iter[kid_id] = gift | n | 108 | 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} | ||
111 | 111 | ||||
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) | ||
120 | 120 | ||||
121 | def xmas(self): | 121 | def xmas(self): | ||
n | 122 | for (kid, kid_id) in dropwhile(lambda kid_entry: kid_entry[1] < 5, self.kid_registry): | n | 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)) | 123 | kid(self.get_gift(kid_id)) | ||
124 | 124 | ||||
125 | self.iter += 1 | 125 | self.iter += 1 | ||
126 | 126 | ||||
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] += 1 | 128 | self.kid_registry[kid_id][1] += 1 | ||
129 | 129 | ||||
130 | def register_kid(self, kid): | 130 | def register_kid(self, kid): | ||
t | 131 | self.kid_registry[id(kid)] = (kid, 0) | t | 131 | self.kid_registry[id(kid)] = [kid, 0] |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | # type: ignore | f | 1 | # type: ignore |
2 | 2 | ||||
3 | from itertools import takewhile, dropwhile | 3 | from itertools import takewhile, dropwhile | ||
4 | from re import search | 4 | from re import search | ||
5 | from random import choice | 5 | from random import choice | ||
6 | from collections import Counter | 6 | from collections import Counter | ||
7 | 7 | ||||
8 | 8 | ||||
9 | class Singleton(type): | 9 | class Singleton(type): | ||
10 | 10 | ||||
11 | def __new__(cls, name, bases, attr_dict): | 11 | def __new__(cls, name, bases, attr_dict): | ||
12 | cls_instances = {} | 12 | cls_instances = {} | ||
13 | 13 | ||||
14 | def singleton_new(inner_cls): | 14 | def singleton_new(inner_cls): | ||
15 | identity = id(inner_cls) | 15 | identity = id(inner_cls) | ||
16 | 16 | ||||
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) | ||
n | n | 22 | class_instance.iter = 0 | ||
23 | class_instance.iter_registry = [{}] | ||||
24 | class_instance.kid_registry = {} | ||||
22 | cls_instances[identity] = class_instance | 25 | cls_instances[identity] = class_instance | ||
23 | return class_instance | 26 | return class_instance | ||
24 | 27 | ||||
25 | attr_dict['__new__'] = singleton_new | 28 | attr_dict['__new__'] = singleton_new | ||
26 | 29 | ||||
27 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | 30 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | ||
28 | 31 | ||||
29 | return singleton_instance | 32 | return singleton_instance | ||
30 | 33 | ||||
31 | 34 | ||||
32 | class Kid(type): | 35 | class Kid(type): | ||
33 | def __new__(cls, name, bases, attr_dict): | 36 | def __new__(cls, name, bases, attr_dict): | ||
34 | 37 | ||||
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 :))))))))))))))))))') | ||
37 | 40 | ||||
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) | ||
40 | 43 | ||||
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] | ||
43 | 46 | ||||
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 exception | 52 | raise exception | ||
50 | 53 | ||||
51 | kid_instance[prop] = new_impl | 54 | kid_instance[prop] = new_impl | ||
52 | 55 | ||||
53 | Santa().register_kid(kid_instance) | 56 | Santa().register_kid(kid_instance) | ||
54 | 57 | ||||
55 | return kid_instance | 58 | return kid_instance | ||
56 | 59 | ||||
57 | attr_dict['__new__'] = kidmeta_new | 60 | attr_dict['__new__'] = kidmeta_new | ||
58 | 61 | ||||
59 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | 62 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | ||
60 | 63 | ||||
61 | return kidmeta_instance | 64 | return kidmeta_instance | ||
62 | 65 | ||||
63 | 66 | ||||
64 | class Santa(metaclass=Singleton): | 67 | class Santa(metaclass=Singleton): | ||
65 | @staticmethod | 68 | @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] | ||
68 | 71 | ||||
69 | @staticmethod | 72 | @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 = None | 75 | kid_id = None | ||
73 | 76 | ||||
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 | break | 80 | break | ||
78 | 81 | ||||
79 | return [kid_id, gift] | 82 | return [kid_id, gift] | ||
80 | 83 | ||||
81 | @property | 84 | @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] | ||
84 | 87 | ||||
t | 85 | 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)] | ||
92 | 90 | ||||
93 | self._upsert_gift(kid_id, gift) | 91 | self._upsert_gift(kid_id, gift) | ||
94 | 92 | ||||
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) | ||
97 | 95 | ||||
98 | self._upsert_gift(kid_id, gift) | 96 | self._upsert_gift(kid_id, gift) | ||
99 | 97 | ||||
100 | def __iter__(self): | 98 | def __iter__(self): | ||
101 | current_iter = self.current_iter.values() | 99 | current_iter = self.current_iter.values() | ||
102 | 100 | ||||
103 | def _iter(): | 101 | def _iter(): | ||
104 | yield from current_iter | 102 | yield from current_iter | ||
105 | 103 | ||||
106 | return _iter | 104 | return _iter | ||
107 | 105 | ||||
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] = gift | 108 | 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} | ||
113 | 111 | ||||
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) | ||
122 | 120 | ||||
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)) | ||
126 | 124 | ||||
127 | self.iter += 1 | 125 | self.iter += 1 | ||
128 | 126 | ||||
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] += 1 | 128 | self.kid_registry[kid_id][1] += 1 | ||
131 | 129 | ||||
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 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | # type: ignore | f | 1 | # type: ignore |
2 | 2 | ||||
3 | from itertools import takewhile, dropwhile | 3 | from itertools import takewhile, dropwhile | ||
4 | from re import search | 4 | from re import search | ||
5 | from random import choice | 5 | from random import choice | ||
6 | from collections import Counter | 6 | from collections import Counter | ||
7 | 7 | ||||
8 | 8 | ||||
9 | class Singleton(type): | 9 | class Singleton(type): | ||
10 | 10 | ||||
11 | def __new__(cls, name, bases, attr_dict): | 11 | def __new__(cls, name, bases, attr_dict): | ||
12 | cls_instances = {} | 12 | cls_instances = {} | ||
13 | 13 | ||||
14 | def singleton_new(inner_cls): | 14 | def singleton_new(inner_cls): | ||
15 | identity = id(inner_cls) | 15 | identity = id(inner_cls) | ||
16 | 16 | ||||
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_instance | 22 | cls_instances[identity] = class_instance | ||
23 | return class_instance | 23 | return class_instance | ||
24 | 24 | ||||
25 | attr_dict['__new__'] = singleton_new | 25 | attr_dict['__new__'] = singleton_new | ||
26 | 26 | ||||
27 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | 27 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | ||
28 | 28 | ||||
29 | return singleton_instance | 29 | return singleton_instance | ||
30 | 30 | ||||
31 | 31 | ||||
32 | class Kid(type): | 32 | class Kid(type): | ||
33 | def __new__(cls, name, bases, attr_dict): | 33 | def __new__(cls, name, bases, attr_dict): | ||
34 | 34 | ||||
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 :))))))))))))))))))') | ||
37 | 37 | ||||
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) | ||
40 | 40 | ||||
t | 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)): | t | 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)): |
42 | old_impl = kid_instance[prop] | 42 | old_impl = kid_instance[prop] | ||
43 | 43 | ||||
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 exception | 49 | raise exception | ||
50 | 50 | ||||
51 | kid_instance[prop] = new_impl | 51 | kid_instance[prop] = new_impl | ||
52 | 52 | ||||
53 | Santa().register_kid(kid_instance) | 53 | Santa().register_kid(kid_instance) | ||
54 | 54 | ||||
55 | return kid_instance | 55 | return kid_instance | ||
56 | 56 | ||||
57 | attr_dict['__new__'] = kidmeta_new | 57 | attr_dict['__new__'] = kidmeta_new | ||
58 | 58 | ||||
59 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | 59 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | ||
60 | 60 | ||||
61 | return kidmeta_instance | 61 | return kidmeta_instance | ||
62 | 62 | ||||
63 | 63 | ||||
64 | class Santa(metaclass=Singleton): | 64 | class Santa(metaclass=Singleton): | ||
65 | @staticmethod | 65 | @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] | ||
68 | 68 | ||||
69 | @staticmethod | 69 | @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 = None | 72 | kid_id = None | ||
73 | 73 | ||||
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 | break | 77 | break | ||
78 | 78 | ||||
79 | return [kid_id, gift] | 79 | return [kid_id, gift] | ||
80 | 80 | ||||
81 | @property | 81 | @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] | ||
84 | 84 | ||||
85 | def __init__(self): | 85 | def __init__(self): | ||
86 | self.iter = 0 | 86 | self.iter = 0 | ||
87 | self.iter_registry = [{}] | 87 | self.iter_registry = [{}] | ||
88 | self.kid_registry = {} | 88 | self.kid_registry = {} | ||
89 | 89 | ||||
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)] | ||
92 | 92 | ||||
93 | self._upsert_gift(kid_id, gift) | 93 | self._upsert_gift(kid_id, gift) | ||
94 | 94 | ||||
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) | ||
97 | 97 | ||||
98 | self._upsert_gift(kid_id, gift) | 98 | self._upsert_gift(kid_id, gift) | ||
99 | 99 | ||||
100 | def __iter__(self): | 100 | def __iter__(self): | ||
101 | current_iter = self.current_iter.values() | 101 | current_iter = self.current_iter.values() | ||
102 | 102 | ||||
103 | def _iter(): | 103 | def _iter(): | ||
104 | yield from current_iter | 104 | yield from current_iter | ||
105 | 105 | ||||
106 | return _iter | 106 | return _iter | ||
107 | 107 | ||||
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] = gift | 110 | 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} | ||
113 | 113 | ||||
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) | ||
122 | 122 | ||||
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)) | ||
126 | 126 | ||||
127 | self.iter += 1 | 127 | self.iter += 1 | ||
128 | 128 | ||||
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] += 1 | 130 | self.kid_registry[kid_id][1] += 1 | ||
131 | 131 | ||||
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 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | # type: ignore | f | 1 | # type: ignore |
2 | 2 | ||||
3 | from itertools import takewhile, dropwhile | 3 | from itertools import takewhile, dropwhile | ||
4 | from re import search | 4 | from re import search | ||
5 | from random import choice | 5 | from random import choice | ||
6 | from collections import Counter | 6 | from collections import Counter | ||
7 | 7 | ||||
8 | 8 | ||||
9 | class Singleton(type): | 9 | class Singleton(type): | ||
10 | 10 | ||||
11 | def __new__(cls, name, bases, attr_dict): | 11 | def __new__(cls, name, bases, attr_dict): | ||
12 | cls_instances = {} | 12 | cls_instances = {} | ||
13 | 13 | ||||
14 | def singleton_new(inner_cls): | 14 | def singleton_new(inner_cls): | ||
15 | identity = id(inner_cls) | 15 | identity = id(inner_cls) | ||
16 | 16 | ||||
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_instance | 22 | cls_instances[identity] = class_instance | ||
23 | return class_instance | 23 | return class_instance | ||
24 | 24 | ||||
25 | attr_dict['__new__'] = singleton_new | 25 | attr_dict['__new__'] = singleton_new | ||
26 | 26 | ||||
27 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | 27 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | ||
28 | 28 | ||||
29 | return singleton_instance | 29 | return singleton_instance | ||
30 | 30 | ||||
31 | 31 | ||||
32 | class Kid(type): | 32 | class Kid(type): | ||
33 | def __new__(cls, name, bases, attr_dict): | 33 | def __new__(cls, name, bases, attr_dict): | ||
34 | 34 | ||||
n | n | 35 | 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) | ||
37 | 40 | ||||
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] | ||
40 | 43 | ||||
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 exception | 49 | raise exception | ||
47 | 50 | ||||
48 | kid_instance[prop] = new_impl | 51 | kid_instance[prop] = new_impl | ||
49 | 52 | ||||
t | 50 | 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) | ||
54 | 54 | ||||
55 | return kid_instance | 55 | return kid_instance | ||
56 | 56 | ||||
57 | attr_dict['__new__'] = kidmeta_new | 57 | attr_dict['__new__'] = kidmeta_new | ||
58 | 58 | ||||
59 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | 59 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | ||
60 | 60 | ||||
61 | return kidmeta_instance | 61 | return kidmeta_instance | ||
62 | 62 | ||||
63 | 63 | ||||
64 | class Santa(metaclass=Singleton): | 64 | class Santa(metaclass=Singleton): | ||
65 | @staticmethod | 65 | @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] | ||
68 | 68 | ||||
69 | @staticmethod | 69 | @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 = None | 72 | kid_id = None | ||
73 | 73 | ||||
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 | break | 77 | break | ||
78 | 78 | ||||
79 | return [kid_id, gift] | 79 | return [kid_id, gift] | ||
80 | 80 | ||||
81 | @property | 81 | @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] | ||
84 | 84 | ||||
85 | def __init__(self): | 85 | def __init__(self): | ||
86 | self.iter = 0 | 86 | self.iter = 0 | ||
87 | self.iter_registry = [{}] | 87 | self.iter_registry = [{}] | ||
88 | self.kid_registry = {} | 88 | self.kid_registry = {} | ||
89 | 89 | ||||
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)] | ||
92 | 92 | ||||
93 | self._upsert_gift(kid_id, gift) | 93 | self._upsert_gift(kid_id, gift) | ||
94 | 94 | ||||
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) | ||
97 | 97 | ||||
98 | self._upsert_gift(kid_id, gift) | 98 | self._upsert_gift(kid_id, gift) | ||
99 | 99 | ||||
100 | def __iter__(self): | 100 | def __iter__(self): | ||
101 | current_iter = self.current_iter.values() | 101 | current_iter = self.current_iter.values() | ||
102 | 102 | ||||
103 | def _iter(): | 103 | def _iter(): | ||
104 | yield from current_iter | 104 | yield from current_iter | ||
105 | 105 | ||||
106 | return _iter | 106 | return _iter | ||
107 | 107 | ||||
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] = gift | 110 | 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} | ||
113 | 113 | ||||
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) | ||
122 | 122 | ||||
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)) | ||
126 | 126 | ||||
127 | self.iter += 1 | 127 | self.iter += 1 | ||
128 | 128 | ||||
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] += 1 | 130 | self.kid_registry[kid_id][1] += 1 | ||
131 | 131 | ||||
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 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | # type: ignore | f | 1 | # type: ignore |
2 | 2 | ||||
3 | from itertools import takewhile, dropwhile | 3 | from itertools import takewhile, dropwhile | ||
4 | from re import search | 4 | from re import search | ||
5 | from random import choice | 5 | from random import choice | ||
6 | from collections import Counter | 6 | from collections import Counter | ||
7 | 7 | ||||
8 | 8 | ||||
9 | class Singleton(type): | 9 | class Singleton(type): | ||
10 | 10 | ||||
11 | def __new__(cls, name, bases, attr_dict): | 11 | def __new__(cls, name, bases, attr_dict): | ||
12 | cls_instances = {} | 12 | cls_instances = {} | ||
13 | 13 | ||||
14 | def singleton_new(inner_cls): | 14 | def singleton_new(inner_cls): | ||
15 | identity = id(inner_cls) | 15 | identity = id(inner_cls) | ||
16 | 16 | ||||
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_instance | 22 | cls_instances[identity] = class_instance | ||
23 | return class_instance | 23 | return class_instance | ||
24 | 24 | ||||
25 | attr_dict['__new__'] = singleton_new | 25 | attr_dict['__new__'] = singleton_new | ||
26 | 26 | ||||
27 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | 27 | singleton_instance = super().__new__(cls, name, bases, attr_dict) | ||
28 | 28 | ||||
29 | return singleton_instance | 29 | return singleton_instance | ||
30 | 30 | ||||
31 | 31 | ||||
32 | class Kid(type): | 32 | class Kid(type): | ||
33 | def __new__(cls, name, bases, attr_dict): | 33 | def __new__(cls, name, bases, attr_dict): | ||
34 | 34 | ||||
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) | ||
37 | 37 | ||||
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] | ||
40 | 40 | ||||
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 exception | 46 | raise exception | ||
47 | 47 | ||||
48 | kid_instance[prop] = new_impl | 48 | kid_instance[prop] = new_impl | ||
49 | 49 | ||||
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) | ||
54 | 54 | ||||
55 | return kid_instance | 55 | return kid_instance | ||
56 | 56 | ||||
57 | attr_dict['__new__'] = kidmeta_new | 57 | attr_dict['__new__'] = kidmeta_new | ||
58 | 58 | ||||
59 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | 59 | kidmeta_instance = super().__new__(cls, name, bases, attr_dict) | ||
60 | 60 | ||||
61 | return kidmeta_instance | 61 | return kidmeta_instance | ||
62 | 62 | ||||
63 | 63 | ||||
64 | class Santa(metaclass=Singleton): | 64 | class Santa(metaclass=Singleton): | ||
65 | @staticmethod | 65 | @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] | ||
68 | 68 | ||||
69 | @staticmethod | 69 | @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 = None | 72 | kid_id = None | ||
73 | 73 | ||||
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 | break | 77 | break | ||
78 | 78 | ||||
79 | return [kid_id, gift] | 79 | return [kid_id, gift] | ||
80 | 80 | ||||
81 | @property | 81 | @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] | ||
84 | 84 | ||||
85 | def __init__(self): | 85 | def __init__(self): | ||
86 | self.iter = 0 | 86 | self.iter = 0 | ||
87 | self.iter_registry = [{}] | 87 | self.iter_registry = [{}] | ||
88 | self.kid_registry = {} | 88 | self.kid_registry = {} | ||
89 | 89 | ||||
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)] | ||
92 | 92 | ||||
93 | self._upsert_gift(kid_id, gift) | 93 | self._upsert_gift(kid_id, gift) | ||
94 | 94 | ||||
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) | ||
97 | 97 | ||||
98 | self._upsert_gift(kid_id, gift) | 98 | self._upsert_gift(kid_id, gift) | ||
99 | 99 | ||||
100 | def __iter__(self): | 100 | def __iter__(self): | ||
101 | current_iter = self.current_iter.values() | 101 | current_iter = self.current_iter.values() | ||
102 | 102 | ||||
103 | def _iter(): | 103 | def _iter(): | ||
104 | yield from current_iter | 104 | yield from current_iter | ||
105 | 105 | ||||
106 | return _iter | 106 | return _iter | ||
107 | 107 | ||||
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] = gift | 110 | 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} | ||
113 | 113 | ||||
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) | ||
122 | 122 | ||||
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)) | ||
126 | 126 | ||||
127 | self.iter += 1 | 127 | self.iter += 1 | ||
128 | 128 | ||||
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] += 1 | 130 | self.kid_registry[kid_id][1] += 1 | ||
131 | 131 | ||||
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) | ||
t | 134 | t | |||
135 | |||||
136 | # santa1 = Santa() | ||||
137 | # santa2 = Santa() | ||||
138 | |||||
139 | # print(f"santa 1 is santa2: {santa1 is santa2}") | ||||
140 | |||||
141 | |||||
142 | class 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 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
20.12.2024 11:08
20.12.2024 11:09
20.12.2024 11:13
20.12.2024 11:18
20.12.2024 11:19
20.12.2024 11:20
20.12.2024 11:20
20.12.2024 11:21