1import re
2import random
3
4
5class Santa:
6 _instance = None
7
8 def __new__(cls, *args, **kwargs):
9 if cls._instance is None:
10 cls._instance = super(Santa, cls).__new__(cls)
11 cls._instance._kids = {}
12 cls._instance._presents = {}
13 cls._instance._present_counts = {}
14 cls._instance._year_counts = {}
15 cls._instance._naughty_kids = []
16 return cls._instance
17
18 def _add_kid(self, kid):
19 kid_id = id(kid)
20 self._kids[kid_id] = kid
21 self._year_counts[kid_id] = 0
22
23 def _add_present_for_kid(self, kid, present):
24 self._presents[id(kid)] = present
25 if present not in self._present_counts:
26 self._present_counts[present] = 0
27 self._present_counts[present] += 1
28
29 def _extract_present_from_request(self, request):
30 present_match = re.search(r'"([A-Za-z0-9\s]*)"|\'([A-Za-z0-9\s]*)\'', request)
31 if present_match:
32 return present_match.group(1) or present_match.group(2)
33 return None
34
35 def __call__(self, kid, request):
36 present = self._extract_present_from_request(request)
37 self._add_present_for_kid(kid, present)
38
39 def __matmul__(self, letter):
40 id_match = re.search(r'\b(\d+)\b', letter)
41 if id_match:
42 kid_id = int(id_match.group(1))
43 if kid_id in self._kids:
44 present = self._extract_present_from_request(letter)
45 self._add_present_for_kid(self._kids[kid_id], present)
46
47 def __iter__(self):
48 for present in self._presents.values():
49 yield present
50
51 def _get_most_requested_present(self):
52 if not self._present_counts:
53 return None
54 max_count = max(self._present_counts.values())
55 most_requested = [pr for pr, count in self._present_counts.items() if count == max_count]
56 return random.choice(most_requested)
57
58 def _is_kid_grown_up(self, kid_id):
59 return self._year_counts.get(kid_id, 0) >= 5
60
61 def _is_kid_naughty(self, kid_id):
62 return self._naughty_kids.count(kid_id)
63
64 def _remove_kid(self, kid_id):
65 self._kids.pop(kid_id, None)
66 self._presents.pop(kid_id, None)
67 self._year_counts.pop(kid_id, None)
68 if kid_id in self._naughty_kids:
69 self._naughty_kids.remove(kid_id)
70
71 def _clear_requests(self):
72 self._presents.clear()
73 self._present_counts.clear()
74
75 def _increment_xmas_counts(self):
76 for kid_id in self._year_counts:
77 self._year_counts[kid_id] += 1
78
79 def xmas(self):
80 most_requested_present = self._get_most_requested_present()
81 kids_to_remove = []
82 for kid_id, kid in self._kids.items():
83 if self._presents and self._present_counts:
84 if self._is_kid_grown_up(kid_id):
85 kids_to_remove.append(kid_id)
86 continue
87 elif self._presents.get(kid_id, False) and self._is_kid_naughty(kid_id):
88 kid("coal")
89 else:
90 present = self._presents.get(kid_id, most_requested_present)
91 kid(present)
92 self._year_counts[kid_id] += 1
93
94 for kid_id in kids_to_remove:
95 self._remove_kid(kid_id)
96
97 self._clear_requests()
98
99
100# опитах да използвам нещо подобно на декоратор (не баш) за логиката с непослушните деца
101# може би има и по - елегантен начин :D
102def naughty_checker(func, kid):
103 def wrapper(*args, **kwargs):
104 santa = Santa()
105 try:
106 return func(*args, **kwargs)
107 except Exception:
108 santa._naughty_kids.append(id(kid))
109 raise
110 return wrapper
111
112
113class Kid(type):
114
115 def __new__(cls, name, bases, attr_dict):
116 if "__call__" not in attr_dict:
117 raise NotImplementedError("__call__ is not implemented by the kid!")
118 return super().__new__(cls, name, bases, attr_dict)
119
120 def __call__(cls, *args, **kwargs):
121 instance = super(Kid, cls).__call__(*args, **kwargs)
122 santa = Santa()
123 santa._add_kid(instance)
124
125 for attr_name in dir(instance):
126 attribute = getattr(instance, attr_name)
127 if not attr_name.startswith('_') and callable(attribute):
128 setattr(instance, attr_name, naughty_checker(attribute, instance))
129
130 return instance
........F...........
======================================================================
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 119, in test_signature_matching
self.assertEqual(kid2.SECRET_PRESENT, 'toy2')
AssertionError: 'toy1' != 'toy2'
- toy1
? ^
+ toy2
? ^
----------------------------------------------------------------------
Ran 20 tests in 0.023s
FAILED (failures=1)
Стефан Шиваров
19.12.2024 18:07Функцията ```increment_xmas_counts``` е излишна. Бях я написал първоначално, когато имах друга последователност на изпълнението в xmas(), но сега виждам, че съм забравил да я махна 😀
|
20.12.2024 11:00
20.12.2024 11:01
20.12.2024 11:04
20.12.2024 11:05