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

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

5 точки общо

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

  1import re
  2from collections import Counter #for the most wanted items
  3
  4class Singleton(type):
  5    def __new__(cls, name, bases, attrs):
  6        def singleton_new(cls):
  7            if not hasattr(cls, 'instance'):
  8                cls.instance = object.__new__(cls)
  9            return cls.instance
 10        attrs['__new__'] = singleton_new
 11        return type.__new__(cls, name, bases, attrs)
 12
 13def matcher(regex, string):
 14    """Да, копирах Ви кода, за да ползвам регулярен израз за желанията"""
 15    match = re.search(regex, string)
 16    if match is None:
 17        return string
 18    # match.group(1) to get only the content within the quotes
 19    return match.group(1)
 20
 21def match_wish (wish: str) -> str:
 22    """Explanation cuz I feel like it works na magiq malko:"""
 23    # [' "] - matches either type of quotation
 24    # [A-Za-z0-9 ]+ - matches letters and numbers (1 or more in the interval)
 25    # [' "] - matches the closing quotation
 26    regex = r'[\'\"]([A-Za-z0-9 ]+)[\'\"]'
 27    return matcher(regex, wish)
 28
 29def match_id(text: str) -> str:
 30    """Matches the line that has the kid's id in it """
 31    regex = r'^\s*\d+\s*$' # not the biggest fan of these things *crying emoji*
 32    # splitting the text into lines so as to search for the one with the id
 33    for line in text.splitlines():
 34        if re.match(regex, line):
 35            return line
 36    return text
 37
 38
 39class Kid(type):
 40    def __new__(cls, name, bases, attrs):
 41        if "__call__" not in attrs:
 42            raise NotImplementedError("Shte se grumna, ne e istina kolko gulgo q pisha taq prostotiq")
 43        else:
 44            new_cls = type.__new__(cls, name, bases, attrs)
 45            if not hasattr(new_cls, "_children"):
 46                new_cls._children = set()
 47            return new_cls
 48
 49    def __call__(cls, *args, **kwargs):
 50        kid_instance = super().__call__(*args, **kwargs)
 51        if hasattr(cls, '_children'):
 52            cls._children.add(kid_instance)
 53        return kid_instance
 54
 55    @classmethod
 56    def check_naughtiness(cls, kid):
 57       """testing the public methods to check"""
 58       for attr_name in dir(kid):
 59           if not attr_name.startswith("_"):
 60               attr = getattr(kid, attr_name)
 61               if(callable(attr)):
 62                   try:
 63                       attr()
 64                   except Exception:
 65                       kid._naughty = True
 66                       break
 67
 68    @classmethod
 69    def level_up_kid(cls, kid_id):
 70        """increment the age of the kid on Christmas"""
 71        for kid in cls._children:
 72            curr_id = id(kid)
 73            if (curr_id == kid_id):
 74                kid._age += 1
 75
 76    @classmethod
 77    def get_age(cls, kid_id):
 78        for kid in cls._children:
 79            if id(kid) == kid_id:
 80                return kid._age
 81        return None
 82
 83    @classmethod
 84    def is_naughty(cls, kid_id):
 85        for kid in cls._children:
 86            curr_id = id(kid)
 87            if(curr_id == kid_id):
 88                return kid._naughty
 89
 90class Santa(metaclass = Singleton):
 91    def __init__(self):
 92        self.wishes = {} # key->id, value->wish
 93        self.most_wanted_gift = Counter()
 94
 95    def __call__(self, kid, wish: str):
 96        present = match_wish(wish)
 97        self.wishes[id(kid)] = present
 98        self.most_wanted_gift[present] += 1
 99
100    def  __matmul__(self, letter: str):
101        present = match_wish(letter)
102        kid_id = match_id(letter)
103        self.wishes[kid_id] = present
104        self.most_wanted_gift[present] += 1
105
106    def __iter__(self):
107        # using the iter function so as to create a new iterator every time
108        return iter(self.wishes.values())
109
110    def xmas(self):
111        if not self.wishes:
112            return #dqdo koleda otiva na borsata, nqma rabota, kriza kriza
113        for kid_id in self.wishes.keys():
114            if Kid.get_age(kid_id) >= 5:
115                continue # does not receive a present
116            if Kid.is_naughty(kid_id):
117                kid('coal')
118            else:
119                wish = self.wishes.get(kid_id)
120                if wish:
121                    kid(wish)
122                else:
123                    if self.most_wanted_gift:
124                        most_wanted_gift = self.most_wanted_gift.most_common(1)[0][0] #tova ne go znaeh che taka se pravi
125                        kid(most_wanted_gift)
126            Kid.level_up_kid(kid_id)

...F....E.EEEE..EEEE
======================================================================
ERROR: 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 117, in test_signature_matching
self.santa.xmas()
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

======================================================================
ERROR: test_xmass (test.TestSanta.test_xmass)
Test a simple Christmas case.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 140, in test_xmass
self.santa.xmas()
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

======================================================================
ERROR: 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 186, in test_xmass_kid_with_multiple_wishes
self.santa.xmas()
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

======================================================================
ERROR: 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 174, in test_xmass_kid_without_a_wish
self.santa.xmas()
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

======================================================================
ERROR: test_xmass_naughty (test.TestSanta.test_xmass_naughty)
Test a Christmas with naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 226, in test_xmass_naughty
self.santa.xmas()
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

======================================================================
ERROR: 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 239, in test_xmass_private_with_error
self.santa.xmas()
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

======================================================================
ERROR: 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 247, in test_xmass_public_with_no_error
self.santa.xmas()
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

======================================================================
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 212, in test_xmass_years_5_and_over
self.santa.xmas() # Christmas 6
^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

======================================================================
ERROR: 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 193, in test_xmass_years_under_5
self.santa.xmas() # Christmas 1
^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 114, in xmas
if Kid.get_age(kid_id) >= 5:
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in get_age
for kid in cls._children:
^^^^^^^^^^^^^
AttributeError: type object 'Kid' has no attribute '_children'

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

----------------------------------------------------------------------
Ran 20 tests in 0.033s

FAILED (failures=1, errors=9)

Дискусия
Георги Кунчев
20.12.2024 10:56

Класът `Santa` е добре. Класът `Kid` не. На въпроса ти - дадох малко информация и горе. Можеш да използваш декоратори, за да следиш дали има грешки в публичните методи. Ако държиш всички създадени деца в някаква колекция, закачена като клас атрибут на `Kid`, ще можеш сама да следиш колко време е минало като отброяваш колко пъти е извикан `xmas`. Има доста варианти това да се направи. Можеш да видиш моето решение, в което имам клас посредник - елф, който се грици за това. Но не е нужно да имаш посредник. Цялата информация може да се пази и в `Kid`. Посредникът помага да се отделят отговорностите.
Екатерина Стоянова
19.12.2024 17:56

Знам, че решението е малоумно, но упорито си играех да направя така, че самият метаклас за Децата да се грижи за техните години и това дали са непослушни. Очевидно, не ми се получи, но искам да ви попитам как би трябвало да стане, без да се запазват самите години и списък с непослушните деца от класа на Дядо Коледа? Благодаря предварително и извинете, че предавам в последния момент, но за жалост съм програмист, който прокрастинира.
История

f1import ref1import re
2from collections import Counter #for the most wanted items2from collections import Counter #for the most wanted items
33
4class Singleton(type):4class Singleton(type):
5    def __new__(cls, name, bases, attrs):5    def __new__(cls, name, bases, attrs):
6        def singleton_new(cls):6        def singleton_new(cls):
7            if not hasattr(cls, 'instance'):7            if not hasattr(cls, 'instance'):
8                cls.instance = object.__new__(cls)8                cls.instance = object.__new__(cls)
9            return cls.instance9            return cls.instance
10        attrs['__new__'] = singleton_new10        attrs['__new__'] = singleton_new
11        return type.__new__(cls, name, bases, attrs)11        return type.__new__(cls, name, bases, attrs)
1212
13def matcher(regex, string):13def matcher(regex, string):
14    """Да, копирах Ви кода, за да ползвам регулярен израз за желанията"""14    """Да, копирах Ви кода, за да ползвам регулярен израз за желанията"""
15    match = re.search(regex, string)15    match = re.search(regex, string)
16    if match is None:16    if match is None:
17        return string17        return string
18    # match.group(1) to get only the content within the quotes18    # match.group(1) to get only the content within the quotes
19    return match.group(1)19    return match.group(1)
2020
21def match_wish (wish: str) -> str:21def match_wish (wish: str) -> str:
22    """Explanation cuz I feel like it works na magiq malko:"""22    """Explanation cuz I feel like it works na magiq malko:"""
23    # [' "] - matches either type of quotation23    # [' "] - matches either type of quotation
24    # [A-Za-z0-9 ]+ - matches letters and numbers (1 or more in the interval)24    # [A-Za-z0-9 ]+ - matches letters and numbers (1 or more in the interval)
25    # [' "] - matches the closing quotation25    # [' "] - matches the closing quotation
26    regex = r'[\'\"]([A-Za-z0-9 ]+)[\'\"]'26    regex = r'[\'\"]([A-Za-z0-9 ]+)[\'\"]'
27    return matcher(regex, wish)27    return matcher(regex, wish)
2828
29def match_id(text: str) -> str:29def match_id(text: str) -> str:
30    """Matches the line that has the kid's id in it """30    """Matches the line that has the kid's id in it """
31    regex = r'^\s*\d+\s*$' # not the biggest fan of these things *crying emoji*31    regex = r'^\s*\d+\s*$' # not the biggest fan of these things *crying emoji*
32    # splitting the text into lines so as to search for the one with the id32    # splitting the text into lines so as to search for the one with the id
33    for line in text.splitlines():33    for line in text.splitlines():
34        if re.match(regex, line):34        if re.match(regex, line):
35            return line35            return line
36    return text36    return text
3737
3838
39class Kid(type):39class Kid(type):
40    def __new__(cls, name, bases, attrs):40    def __new__(cls, name, bases, attrs):
41        if "__call__" not in attrs:41        if "__call__" not in attrs:
42            raise NotImplementedError("Shte se grumna, ne e istina kolko gulgo q pisha taq prostotiq")42            raise NotImplementedError("Shte se grumna, ne e istina kolko gulgo q pisha taq prostotiq")
43        else:43        else:
44            new_cls = type.__new__(cls, name, bases, attrs)44            new_cls = type.__new__(cls, name, bases, attrs)
45            if not hasattr(new_cls, "_children"):45            if not hasattr(new_cls, "_children"):
46                new_cls._children = set()46                new_cls._children = set()
47            return new_cls47            return new_cls
4848
49    def __call__(cls, *args, **kwargs):49    def __call__(cls, *args, **kwargs):
50        kid_instance = super().__call__(*args, **kwargs)50        kid_instance = super().__call__(*args, **kwargs)
51        if hasattr(cls, '_children'):51        if hasattr(cls, '_children'):
52            cls._children.add(kid_instance)52            cls._children.add(kid_instance)
53        return kid_instance53        return kid_instance
5454
55    @classmethod55    @classmethod
56    def check_naughtiness(cls, kid):56    def check_naughtiness(cls, kid):
57       """testing the public methods to check"""57       """testing the public methods to check"""
58       for attr_name in dir(kid):58       for attr_name in dir(kid):
59           if not attr_name.startswith("_"):59           if not attr_name.startswith("_"):
60               attr = getattr(kid, attr_name)60               attr = getattr(kid, attr_name)
61               if(callable(attr)):61               if(callable(attr)):
62                   try:62                   try:
63                       attr()63                       attr()
64                   except Exception:64                   except Exception:
65                       kid._naughty = True65                       kid._naughty = True
66                       break66                       break
6767
68    @classmethod68    @classmethod
69    def level_up_kid(cls, kid_id):69    def level_up_kid(cls, kid_id):
70        """increment the age of the kid on Christmas"""70        """increment the age of the kid on Christmas"""
71        for kid in cls._children:71        for kid in cls._children:
72            curr_id = id(kid)72            curr_id = id(kid)
73            if (curr_id == kid_id):73            if (curr_id == kid_id):
74                kid._age += 174                kid._age += 1
7575
76    @classmethod76    @classmethod
77    def get_age(cls, kid_id):77    def get_age(cls, kid_id):
78        for kid in cls._children:78        for kid in cls._children:
79            if id(kid) == kid_id:79            if id(kid) == kid_id:
80                return kid._age80                return kid._age
81        return None81        return None
8282
83    @classmethod83    @classmethod
84    def is_naughty(cls, kid_id):84    def is_naughty(cls, kid_id):
85        for kid in cls._children:85        for kid in cls._children:
86            curr_id = id(kid)86            curr_id = id(kid)
87            if(curr_id == kid_id):87            if(curr_id == kid_id):
88                return kid._naughty88                return kid._naughty
8989
90class Santa(metaclass = Singleton):90class Santa(metaclass = Singleton):
91    def __init__(self):91    def __init__(self):
92        self.wishes = {} # key->id, value->wish92        self.wishes = {} # key->id, value->wish
93        self.most_wanted_gift = Counter()93        self.most_wanted_gift = Counter()
9494
95    def __call__(self, kid, wish: str):95    def __call__(self, kid, wish: str):
96        present = match_wish(wish)96        present = match_wish(wish)
97        self.wishes[id(kid)] = present97        self.wishes[id(kid)] = present
98        self.most_wanted_gift[present] += 198        self.most_wanted_gift[present] += 1
9999
100    def  __matmul__(self, letter: str):100    def  __matmul__(self, letter: str):
101        present = match_wish(letter)101        present = match_wish(letter)
102        kid_id = match_id(letter)102        kid_id = match_id(letter)
103        self.wishes[kid_id] = present103        self.wishes[kid_id] = present
104        self.most_wanted_gift[present] += 1104        self.most_wanted_gift[present] += 1
105105
106    def __iter__(self):106    def __iter__(self):
107        # using the iter function so as to create a new iterator every time107        # using the iter function so as to create a new iterator every time
108        return iter(self.wishes.values())108        return iter(self.wishes.values())
109109
110    def xmas(self):110    def xmas(self):
111        if not self.wishes:111        if not self.wishes:
112            return #dqdo koleda otiva na borsata, nqma rabota, kriza kriza112            return #dqdo koleda otiva na borsata, nqma rabota, kriza kriza
113        for kid_id in self.wishes.keys():113        for kid_id in self.wishes.keys():
114            if Kid.get_age(kid_id) >= 5:114            if Kid.get_age(kid_id) >= 5:
115                continue # does not receive a present115                continue # does not receive a present
116            if Kid.is_naughty(kid_id):116            if Kid.is_naughty(kid_id):
117                kid('coal')117                kid('coal')
118            else:118            else:
119                wish = self.wishes.get(kid_id)119                wish = self.wishes.get(kid_id)
120                if wish:120                if wish:
121                    kid(wish)121                    kid(wish)
122                else:122                else:
123                    if self.most_wanted_gift:123                    if self.most_wanted_gift:
124                        most_wanted_gift = self.most_wanted_gift.most_common(1)[0][0] #tova ne go znaeh che taka se pravi124                        most_wanted_gift = self.most_wanted_gift.most_common(1)[0][0] #tova ne go znaeh che taka se pravi
125                        kid(most_wanted_gift)125                        kid(most_wanted_gift)
126            Kid.level_up_kid(kid_id)126            Kid.level_up_kid(kid_id)
127127
t128santa = Santa()t
129 
130 
131class BulgarianKid(metaclass=Kid):
132 
133    def __call__(self, present):
134        self._present = present
135 
136    def be_naughty(self):
137        raise RuntimeError('Няма да си изям зеленчуците!')
138 
139 
140class ChineseKid(metaclass=Kid):
141 
142    def __call__(self, present):
143        self._present = present
144 
145 
146goshko = BulgarianKid()
147toshko = BulgarianKid()
148chen = ChineseKid()
149 
150santa(goshko, "'gun'")
151santa @ f"'gun'\n{id(toshko)}"
152 
153try:
154    goshko.be_naughty()
155except:
156    pass
157 
158santa.xmas()
159# Гошко получава coal
160# Тошко получава gun
161# Chen получава gun
162 
163santa.xmas()
164# Никой не получава нищо, защото няма желания
165 
166santa.xmas()
167# Никой не получава нищо, защото няма желания
168 
169santa.xmas()
170# Никой не получава нищо, защото няма желания
171 
172gencho = BulgarianKid()
173santa(gencho, "'whistle'")
174 
175santa.xmas()
176# Всички деца (Гошко, Тошко, Cheng и Генчо) получават whistle
177 
178kircho = BulgarianKid()
179santa(kircho, "'whistle'")
180 
181santa.xmas()
182# Кирчо и Генчо получават whistle. Останалите вече са на над 5 години.
183 
184 
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op