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

Резултати
8 точки от тестове
1 точки от учител

9 точки общо

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

  1import re
  2 
  3class Singleton(type):
  4    objects = {}
  5    def __call__(cls, *args, **kwargs):
  6        if cls not in cls.objects:
  7            cls.objects[cls] = super().__call__(*args, **kwargs)
  8        return cls.objects[cls] 
  9
 10class Santa(metaclass=Singleton):
 11    _year = 0
 12    _MAX_CHILD_AGE = 5
 13
 14    def __init__(self):
 15        self._wishes = {}
 16        self._curr_year_wishes = []
 17 
 18    @staticmethod
 19    def get_id_from_a_str(text: str) -> int:
 20        match = re.search(r"^\s*(\d+)\s*$", text, re.MULTILINE)
 21        if match:
 22            return int(match.group(1))
 23        return None
 24    
 25    @staticmethod
 26    def get_wish_from_a_str(text: str) -> str:
 27        match = re.search(r'["\']([a-zA-Z0-9 ]+)["\']', text)
 28        if match:
 29            return match.group(1)
 30        return None
 31 
 32    def __call__(self, kid, letter):
 33        wish = self.get_wish_from_a_str(letter)
 34        self._wishes[id(kid)] = wish
 35        self._curr_year_wishes.append(wish)
 36 
 37    def __matmul__(self, other):
 38        child_id = self.get_id_from_a_str(other)
 39        wish = self.get_wish_from_a_str(other)
 40        self._wishes[child_id] = wish
 41        self._curr_year_wishes.append(wish)
 42
 43    def __iter__(self):
 44        return iter(self._curr_year_wishes)
 45 
 46    def xmas(self):
 47        Santa._year += 1
 48        if not self._curr_year_wishes:
 49            self._wishes.clear()
 50            self._curr_year_wishes.clear()
 51            print("The magic is dead :(")
 52            return
 53 
 54        gift_counter = {}
 55        for _, gift in self._wishes.items():
 56            gift_counter[gift] = gift_counter.get(gift, 0) + 1
 57            most_wanted = max(gift_counter, key=gift_counter.get)
 58 
 59        for _, child in Kid.all_children.items():
 60            if Santa._year - Kid.start_year[id(child)] >= Santa._MAX_CHILD_AGE:
 61                continue
 62            if child.naughty:
 63                child('coal')
 64                print("receives: coal")
 65            else:
 66                gift = self._wishes.get(id(child), most_wanted)
 67                child(gift)
 68                print(f"receives: {gift}")
 69 
 70        self._wishes.clear()
 71        self._curr_year_wishes.clear()
 72
 73
 74class Kid(type):
 75    all_children = {}
 76    start_year = {}
 77 
 78    def __new__(cls, name, bases, dct):
 79        if "__call__" not in dct:
 80            raise NotImplementedError("I love you, but I need a __call__ method!... P.S(5 hours later) I hate you this hw almost killed me <3")
 81        for name, value in dct.items():
 82            if not name.startswith('__') and callable(value):
 83                dct[name] = cls.hadle_exceptions(value)
 84        return super().__new__(cls, name, bases, dct)
 85 
 86    def __call__(cls, *args, **kwargs):
 87        instance = super().__call__(*args, **kwargs)
 88        instance.naughty = False
 89        cls.all_children[id(instance)] = instance
 90        cls.start_year[id(instance)] = Santa._year
 91        return instance
 92    
 93    def hadle_exceptions(method):
 94        def wrapper(self, *args, **kwargs):
 95            try:
 96                return method(self, *args, **kwargs)
 97            except Exception:
 98                self.naughty = True
 99                raise
100        return wrapper
101 
102##TESTS
103# class Child(metaclass=Kid):
104#     def __call__(self, present):
105#         pass
106
107# class BulgarianKid(metaclass=Kid):
108#     def __call__(self, present):
109#         pass
110    
111#     def be_naughty(self):
112#         raise RuntimeError('Няма да си изям зеленчуците!')
113
114# class ChineseKid(metaclass=Kid):
115#     def __call__(self, present):
116#         pass
117
118# santa = Santa()
119
120# goshko = BulgarianKid()
121# toshko = BulgarianKid()
122# chen = ChineseKid()
123
124# # Santa receiving wishes
125# santa(goshko, "'gun'")
126# santa @ f"'gun'\n{id(toshko)}"
127
128# # Handling naughtiness for Goshko
129# try:
130#     goshko.be_naughty()
131# except:
132#     pass
133
134# # Process gifts
135# santa.xmas()
136# # Expected output:
137# # Гошко получава coal
138# # Тошко получава gun
139# # # Chen получава gun
140
141
142# test2 
143# santa = Santa()
144# santa @ "През по-голямата 2945526885456 част от тази година бях много послушен! Понякога бях само леко  но т'ва не е никакъв проблем, защото всички сме хора и понякога искаме да теглим една '...' на всичко. Life is tough! Моля те донеси ми 'doll'."
145# kid1 = Child()
146# santa(kid1, "През по-голямата 2945526885456 част от тази година бях много послушен! Понякога бях само леко  но т'ва не е никакъв проблем, защото всички сме хора и понякога искаме да теглим една '...' на всичко. Life is tough! Моля те донеси ми 'ball'.")
147# for present in santa:
148#     print(present)
149
150#test3
151# santa1 = Santa()
152# santa2 = Santa()
153# print(santa1 is santa2)

...FF..F........F
Stdout:
receives: coal
..F
Stdout:
receives: toy1
The magic is dead :(
The magic is dead :(
The magic is dead :(

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

Stdout:
receives: coal

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

Stdout:
receives: toy1
The magic is dead :(
The magic is dead :(
The magic is dead :(

----------------------------------------------------------------------
Ran 20 tests in 0.027s

FAILED (failures=5)

Дискусия
История
Това решение има само една версия.