1import re
2import random
3
4
5class Kid(type):
6 _all_kids = {}
7 _creation_year = {}
8
9 def __new__(cls, name, bases, dct):
10 if "__call__" not in dct:
11 raise NotImplementedError("Not implemented __call__")
12
13 for name, value in dct.items():
14 if not name.startswith('__') and callable(value):
15 dct[name] = cls.checker(value)
16 return super().__new__(cls, name, bases, dct)
17
18 def checker(method):
19 def wrapper(self, *args, **kwargs):
20 try:
21 return method(self, *args, **kwargs)
22 except Exception:
23 self._is_bad = True
24 raise
25 return wrapper
26
27 def __call__(cls, *args, **kwargs):
28 instance = super().__call__(*args, **kwargs)
29 instance._is_bad = False
30
31 cls._all_kids[id(instance)] = instance
32 cls._creation_year[id(instance)] = Santa._curr_year
33 return instance
34
35
36class Santa:
37 _instance = None
38 _curr_year = 0
39 _MAX_AGE = 5
40
41 def __new__(cls, *args, **kwargs):
42 if cls._instance is None:
43 cls._instance = super().__new__(cls)
44 cls._instance._initialized = False
45 return cls._instance
46
47 def __init__(self):
48 if not self._initialized:
49 self._wishes = {}
50 self._curr_year_wishes = []
51 self._initialized = True
52
53 def _extract_wish(self, text):
54 match = re.search(r'[\'"]([A-Za-z0-9 ]+)[\'"]', text)
55 return match.group(1) if match else None
56
57 def __call__(self, kid, message):
58 wish = self._extract_wish(message)
59 if wish:
60 self._wishes[id(kid)] = wish
61 self._curr_year_wishes.append(wish)
62
63 def __matmul__(self, other):
64 kid_id = None
65 lines = other.strip().split('\n')
66 for line in lines:
67 if re.match(r'^\s*\d+\s*$', line):
68 kid_id = int(line.strip())
69 break
70
71 if kid_id is None:
72 return
73
74 kid = Kid._all_kids.get(kid_id)
75 if kid:
76 wish = self._extract_wish(other)
77 if wish:
78 self._wishes[kid_id] = wish
79 self._curr_year_wishes.append(wish)
80
81 def __iter__(self):
82 return iter(self._curr_year_wishes)
83
84 def xmas(self):
85 Santa._curr_year += 1
86
87 if not self._curr_year_wishes:
88 self._wishes.clear()
89 self._curr_year_wishes.clear()
90 return
91
92 wish_count = {}
93 max_count = 0
94
95 for wish in self._curr_year_wishes:
96 wish_count[wish] = wish_count.get(wish, 0) + 1
97 max_count = max(max_count, wish_count[wish])
98
99 most_common = [wish for wish, count in wish_count.items() if count == max_count]
100 most_common = random.choice(most_common)
101
102 for kid in Kid._all_kids.values():
103 if Santa._curr_year - Kid._creation_year[id(kid)] >= self._MAX_AGE:
104 continue
105
106 if kid._is_bad:
107 kid('coal')
108 kid._is_bad = False
109 else:
110 gift = self._wishes.get(id(kid), most_common)
111 kid(gift)
112
113 self._wishes.clear()
114 self._curr_year_wishes.clear()
...FF..F........F..F
======================================================================
FAIL: 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'])
AssertionError: Lists differ: ['toy1', 'toy1'] != ['toy1']
First list contains 1 additional elements.
First extra element 1:
'toy1'
- ['toy1', 'toy1']
+ ['toy1']
======================================================================
FAIL: 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 129, in test_iterable
self.assertEqual(list(self.santa), ['something', 'something else'])
AssertionError: Lists differ: ['something', 'something not used', 'something else'] != ['something', 'something else']
First differing element 1:
'something not used'
'something else'
First list contains 1 additional elements.
First extra element 2:
'something else'
- ['something', 'something not used', 'something else']
+ ['something', 'something else']
======================================================================
FAIL: 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"])
AssertionError: Lists differ: ['toy2', 'toy3', 'toy1', 'toy2v2'] != ['toy2v2', 'toy3', 'toy1']
First differing element 0:
'toy2'
'toy2v2'
First list contains 1 additional elements.
First extra element 3:
'toy2v2'
- ['toy2', 'toy3', 'toy1', 'toy2v2']
+ ['toy2v2', 'toy3', 'toy1']
======================================================================
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: 'coal' != 'sirenie'
- coal
+ 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 201, in test_xmass_years_under_5
self.assertEqual(kid1.SECRET_PRESENT, 'toy2')
AssertionError: None != 'toy2'
----------------------------------------------------------------------
Ran 20 tests in 0.061s
FAILED (failures=5)
Виктор Бечев
19.12.2024 17:13Харесва ми колко различни инструмента си използвала из решението си.
Също така си единствената с това решение на проблема с годините. Very nice.
|
19.12.2024 16:58
19.12.2024 16:55
19.12.2024 17:12