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

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

9 точки общо

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

  1import re
  2from collections import OrderedDict, Counter
  3
  4
  5class Singleton(type):
  6    def __new__(cls, name, bases, attrs):
  7        def singleton_new(cls):
  8            if not hasattr(cls, 'instance'):
  9                cls.instance = object.__new__(cls)
 10            return cls.instance
 11        attrs['__new__'] = singleton_new
 12        return super().__new__(cls, name, bases, attrs)
 13
 14
 15class Santa(metaclass=Singleton):
 16    """HOHOHO."""
 17
 18    kid_present = OrderedDict()
 19
 20    def __init__(self):
 21        self.presents_iter = None
 22
 23    def __call__(self, kid, wish: str):
 24        extracted_info = Wish(wish)
 25        self.kid_present[kid] = extracted_info.present
 26
 27    def __matmul__(self, letter: str):
 28        extracted_info = Wish(letter)
 29        self.kid_present[Kid.find_kid(extracted_info.kid_id)] = extracted_info.present
 30
 31    def __iter__(self):
 32        return iter(self.kid_present.values())
 33
 34    def xmas(self):
 35        Kid.increment_age_of_all_kids()
 36
 37        # if there are no wishes return
 38        if not self.kid_present:
 39            return
 40
 41        counted = Counter(self.__iter__())
 42        most_common_present = counted.most_common(1)[0][0]
 43
 44        for kid in Kid.kids_created:
 45            if kid.age > 5:
 46                continue
 47
 48            if kid.naughty:
 49                kid('coal')
 50                kid.naughty = False
 51                continue
 52
 53            present = self.kid_present.get(kid, most_common_present)
 54            kid(present)
 55
 56            # remove kid from wishlist
 57            if kid in self.kid_present:
 58                self.kid_present.pop(kid)
 59
 60
 61class Wish:
 62    """Decipher wish and extract only relevant info."""
 63
 64    def __init__(self, wish: str):
 65        self.present = None
 66        self.kid_id = None
 67
 68        # find present
 69        present_pattern = r'([\'\"])(?P<present>(\s*\w+\s*)+)(\1)'
 70        match = re.search(present_pattern, wish)
 71        if match:
 72            self.present = match.group('present')
 73
 74        # find id if there is one
 75        id_pattern = r'\n\s*(?P<kid_id>\d+)\s*(\n|$)'
 76        match = re.search(id_pattern, wish)
 77        if match:
 78            self.kid_id = int(match.group('kid_id'))
 79
 80
 81class Kid(type):
 82
 83    kids_created = [] # who knows how exactly
 84
 85    def __new__(cls, name, bases, attrs):
 86        # add naughty flag and age to all kids
 87        attrs['naughty'] = False
 88        attrs['age'] = 0
 89
 90        # check if kid is callable
 91        if not attrs.get('__call__', None):
 92            raise NotImplementedError('kur cici kurviiiiiiiiiiii - съобщение от човек не в курса')
 93
 94        # decorate __new__ if it exists in child class and create it if it doesn't
 95        try:
 96            attrs['__new__'] = cls.new_kid_decorator(attrs['__new__'])
 97        except Exception:
 98            attrs['__new__'] = cls.new_kid
 99
100        # wrap all public methods in decorator to check for naughtiness
101        for name, attr in attrs.items():
102            if callable(attr) and not name.startswith('__'):
103                attrs[name] = cls.naughty_decorator(attr)
104
105        return super().__new__(cls, name, bases, attrs)
106
107    @classmethod
108    def find_kid(cls, kid_id: int):
109        for kid in cls.kids_created:
110            if id(kid) == kid_id:
111                return kid
112
113    @staticmethod
114    def new_kid_decorator(func):
115        def decorated(self, *args, **kwargs):
116            Kid.kids_created.append(self)
117            return func(self, *args, **kwargs)
118        return decorated
119
120    @staticmethod
121    def new_kid(cls_kid):
122        instance = object.__new__(cls_kid)
123        Kid.kids_created.append(instance)
124        return instance
125
126    @staticmethod
127    def naughty_decorator(func):
128        def decorated(self, *args, **kwargs):
129            try:
130                res = func(self, *args, **kwargs)
131            except Exception:
132                self.naughty = True
133                raise
134            return res
135        return decorated
136
137    @classmethod
138    def increment_age_of_all_kids(cls):
139        for kid in cls.kids_created:
140            kid.age += 1

......F.........F...
======================================================================
FAIL: test_present_matching (test.TestSanta.test_present_matching)
Test matching signature in the letter.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 92, in test_present_matching
self.assertEqual(list(self.santa), ['toy4', 'abcdefgHIJKLMNopQRstUVwxYZ 1 2 3 4567890 '])
AssertionError: Lists differ: ['кавички', 'abcdefgHIJKLMNopQRstUVwxYZ 1 2 3 4567890 '] != ['toy4', 'abcdefgHIJKLMNopQRstUVwxYZ 1 2 3 4567890 ']

First differing element 0:
'кавички'
'toy4'

- ['кавички', 'abcdefgHIJKLMNopQRstUVwxYZ 1 2 3 4567890 ']
? ^^^^^^^

+ ['toy4', 'abcdefgHIJKLMNopQRstUVwxYZ 1 2 3 4567890 ']
? ^^^^

======================================================================
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

----------------------------------------------------------------------
Ran 20 tests in 0.040s

FAILED (failures=2)

Дискусия
История

f1import ref1import re
2from collections import OrderedDict, Counter2from collections import OrderedDict, Counter
33
44
5class Singleton(type):5class Singleton(type):
6    def __new__(cls, name, bases, attrs):6    def __new__(cls, name, bases, attrs):
7        def singleton_new(cls):7        def singleton_new(cls):
8            if not hasattr(cls, 'instance'):8            if not hasattr(cls, 'instance'):
9                cls.instance = object.__new__(cls)9                cls.instance = object.__new__(cls)
10            return cls.instance10            return cls.instance
11        attrs['__new__'] = singleton_new11        attrs['__new__'] = singleton_new
12        return super().__new__(cls, name, bases, attrs)12        return super().__new__(cls, name, bases, attrs)
1313
1414
15class Santa(metaclass=Singleton):15class Santa(metaclass=Singleton):
16    """HOHOHO."""16    """HOHOHO."""
1717
18    kid_present = OrderedDict()18    kid_present = OrderedDict()
1919
20    def __init__(self):20    def __init__(self):
21        self.presents_iter = None21        self.presents_iter = None
2222
23    def __call__(self, kid, wish: str):23    def __call__(self, kid, wish: str):
24        extracted_info = Wish(wish)24        extracted_info = Wish(wish)
25        self.kid_present[kid] = extracted_info.present25        self.kid_present[kid] = extracted_info.present
2626
27    def __matmul__(self, letter: str):27    def __matmul__(self, letter: str):
28        extracted_info = Wish(letter)28        extracted_info = Wish(letter)
29        self.kid_present[Kid.find_kid(extracted_info.kid_id)] = extracted_info.present29        self.kid_present[Kid.find_kid(extracted_info.kid_id)] = extracted_info.present
3030
31    def __iter__(self):31    def __iter__(self):
t32        self.presents_iter = iter(self.kid_present.values())t32        return iter(self.kid_present.values())
33        return self.presents_iter
34 
35    def __next__(self):
36        return next(self.presents_iter)
3733
38    def xmas(self):34    def xmas(self):
39        Kid.increment_age_of_all_kids()35        Kid.increment_age_of_all_kids()
4036
41        # if there are no wishes return37        # if there are no wishes return
42        if not self.kid_present:38        if not self.kid_present:
43            return39            return
4440
45        counted = Counter(self.__iter__())41        counted = Counter(self.__iter__())
46        most_common_present = counted.most_common(1)[0][0]42        most_common_present = counted.most_common(1)[0][0]
4743
48        for kid in Kid.kids_created:44        for kid in Kid.kids_created:
49            if kid.age > 5:45            if kid.age > 5:
50                continue46                continue
5147
52            if kid.naughty:48            if kid.naughty:
53                kid('coal')49                kid('coal')
54                kid.naughty = False50                kid.naughty = False
55                continue51                continue
5652
57            present = self.kid_present.get(kid, most_common_present)53            present = self.kid_present.get(kid, most_common_present)
58            kid(present)54            kid(present)
5955
60            # remove kid from wishlist56            # remove kid from wishlist
61            if kid in self.kid_present:57            if kid in self.kid_present:
62                self.kid_present.pop(kid)58                self.kid_present.pop(kid)
6359
6460
65class Wish:61class Wish:
66    """Decipher wish and extract only relevant info."""62    """Decipher wish and extract only relevant info."""
6763
68    def __init__(self, wish: str):64    def __init__(self, wish: str):
69        self.present = None65        self.present = None
70        self.kid_id = None66        self.kid_id = None
7167
72        # find present68        # find present
73        present_pattern = r'([\'\"])(?P<present>(\s*\w+\s*)+)(\1)'69        present_pattern = r'([\'\"])(?P<present>(\s*\w+\s*)+)(\1)'
74        match = re.search(present_pattern, wish)70        match = re.search(present_pattern, wish)
75        if match:71        if match:
76            self.present = match.group('present')72            self.present = match.group('present')
7773
78        # find id if there is one74        # find id if there is one
79        id_pattern = r'\n\s*(?P<kid_id>\d+)\s*(\n|$)'75        id_pattern = r'\n\s*(?P<kid_id>\d+)\s*(\n|$)'
80        match = re.search(id_pattern, wish)76        match = re.search(id_pattern, wish)
81        if match:77        if match:
82            self.kid_id = int(match.group('kid_id'))78            self.kid_id = int(match.group('kid_id'))
8379
8480
85class Kid(type):81class Kid(type):
8682
87    kids_created = [] # who knows how exactly83    kids_created = [] # who knows how exactly
8884
89    def __new__(cls, name, bases, attrs):85    def __new__(cls, name, bases, attrs):
90        # add naughty flag and age to all kids86        # add naughty flag and age to all kids
91        attrs['naughty'] = False87        attrs['naughty'] = False
92        attrs['age'] = 088        attrs['age'] = 0
9389
94        # check if kid is callable90        # check if kid is callable
95        if not attrs.get('__call__', None):91        if not attrs.get('__call__', None):
96            raise NotImplementedError('kur cici kurviiiiiiiiiiii - съобщение от човек не в курса')92            raise NotImplementedError('kur cici kurviiiiiiiiiiii - съобщение от човек не в курса')
9793
98        # decorate __new__ if it exists in child class and create it if it doesn't94        # decorate __new__ if it exists in child class and create it if it doesn't
99        try:95        try:
100            attrs['__new__'] = cls.new_kid_decorator(attrs['__new__'])96            attrs['__new__'] = cls.new_kid_decorator(attrs['__new__'])
101        except Exception:97        except Exception:
102            attrs['__new__'] = cls.new_kid98            attrs['__new__'] = cls.new_kid
10399
104        # wrap all public methods in decorator to check for naughtiness100        # wrap all public methods in decorator to check for naughtiness
105        for name, attr in attrs.items():101        for name, attr in attrs.items():
106            if callable(attr) and not name.startswith('__'):102            if callable(attr) and not name.startswith('__'):
107                attrs[name] = cls.naughty_decorator(attr)103                attrs[name] = cls.naughty_decorator(attr)
108104
109        return super().__new__(cls, name, bases, attrs)105        return super().__new__(cls, name, bases, attrs)
110106
111    @classmethod107    @classmethod
112    def find_kid(cls, kid_id: int):108    def find_kid(cls, kid_id: int):
113        for kid in cls.kids_created:109        for kid in cls.kids_created:
114            if id(kid) == kid_id:110            if id(kid) == kid_id:
115                return kid111                return kid
116112
117    @staticmethod113    @staticmethod
118    def new_kid_decorator(func):114    def new_kid_decorator(func):
119        def decorated(self, *args, **kwargs):115        def decorated(self, *args, **kwargs):
120            Kid.kids_created.append(self)116            Kid.kids_created.append(self)
121            return func(self, *args, **kwargs)117            return func(self, *args, **kwargs)
122        return decorated118        return decorated
123119
124    @staticmethod120    @staticmethod
125    def new_kid(cls_kid):121    def new_kid(cls_kid):
126        instance = object.__new__(cls_kid)122        instance = object.__new__(cls_kid)
127        Kid.kids_created.append(instance)123        Kid.kids_created.append(instance)
128        return instance124        return instance
129125
130    @staticmethod126    @staticmethod
131    def naughty_decorator(func):127    def naughty_decorator(func):
132        def decorated(self, *args, **kwargs):128        def decorated(self, *args, **kwargs):
133            try:129            try:
134                res = func(self, *args, **kwargs)130                res = func(self, *args, **kwargs)
135            except Exception:131            except Exception:
136                self.naughty = True132                self.naughty = True
137                raise133                raise
138            return res134            return res
139        return decorated135        return decorated
140136
141    @classmethod137    @classmethod
142    def increment_age_of_all_kids(cls):138    def increment_age_of_all_kids(cls):
143        for kid in cls.kids_created:139        for kid in cls.kids_created:
144            kid.age += 1140            kid.age += 1
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op