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

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

10 точки общо

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

  1import re
  2
  3class Santa:
  4    instance = None
  5    MAX_KID_AGE = 5
  6    COAL_PRESENT = 'coal'
  7
  8    def xmas(self):
  9        for child in self.children.keys():
 10            self.children[child] += 1
 11
 12        if not self.presents:
 13            return
 14
 15        present_counts = dict()
 16        given_presents = set()
 17        for present in self.presents:
 18            if self.children[present[0]] > Santa.MAX_KID_AGE:
 19                continue
 20            given_presents.add(present[0])
 21            if present[0] in self.blacklist:
 22                self.kids_by_id[present[0]](self.COAL_PRESENT)
 23                continue
 24            self.kids_by_id[present[0]](present[1])
 25            present_counts[present[1]] = present_counts.get(present[1], 0) + 1
 26
 27        most_wanted_present = (None, 0)
 28        for name, count in present_counts.items():
 29            if most_wanted_present[1] < count:
 30                most_wanted_present = (name, count)
 31
 32        must_be_good_present = most_wanted_present[0]
 33
 34        for kid, age in self.children.items():
 35            if age > Santa.MAX_KID_AGE or kid in given_presents:
 36                continue
 37            if kid in self.blacklist:
 38                self.kids_by_id[kid](self.COAL_PRESENT)
 39            else:
 40                self.kids_by_id[kid](must_be_good_present)
 41
 42        self.presents = []
 43        self.blacklist = set()
 44
 45    def __new__(cls, *args, **kwargs):
 46        if cls.instance is None:
 47            cls.instance = super().__new__(cls, *args, **kwargs)
 48        return cls.instance
 49
 50    def __init__(self):
 51        self.presents = []
 52        self.blacklist = set()
 53        self.children = dict()
 54        self.kids_by_id = dict()
 55        self._iter_index = 0
 56
 57    def __call__(self, kid, wish):
 58        kid_id = id(kid)
 59        for i, present in enumerate(self.presents):
 60            if present[0] == kid_id:
 61                self.presents[i] = (kid_id, Santa.get_present_wish(wish))
 62                break
 63        else:
 64            self.presents.append((kid_id, Santa.get_present_wish(wish)))
 65
 66    def __matmul__(self, letter):
 67        kid_id = Santa.get_kid_id(letter)
 68        kid_wish = Santa.get_present_wish(letter)
 69        for i, present in enumerate(self.presents):
 70            if present[0] == kid_id:
 71                self.presents[i] = (kid_id, kid_wish)
 72                break
 73        else:
 74            self.presents.append((kid_id, kid_wish))
 75
 76    def __iter__(self):
 77        self._iter_index = 0
 78        return self
 79
 80    def __next__(self):
 81        if self._iter_index >= len(self.presents):
 82            self._iter_index = 0
 83            raise StopIteration
 84        self._iter_index += 1
 85        return self.presents[self._iter_index - 1][1]
 86
 87    @staticmethod
 88    def get_present_wish(wish):
 89        kid_present_r = r"(\"|\')([a-zA-Z0-9]+[a-zA-Z0-9\s]*)\1"
 90        return re.search(kid_present_r, wish).group(2)
 91
 92    @staticmethod
 93    def get_kid_id(letter):
 94        kid_id_r = r"^\s*\d+\s*$"
 95        kid_id = None
 96        for line in letter.splitlines():
 97            if re.match(kid_id_r, line):
 98                kid_id = int(line.strip())
 99                break
100        return kid_id
101
102class Kid(type):
103
104    def __new__(cls, name, bases, attr_dict):
105        if '__call__' not in attr_dict:
106            raise NotImplementedError('No __call__')
107
108        for attr, value in attr_dict.items():
109            if not attr.startswith('_') and hasattr(value, '__call__'):
110                attr_dict[attr] = Kid.bad_kid_checker(value)
111
112        new_class = super().__new__(cls, name, bases, attr_dict)
113        old_new = new_class.__new__
114
115        def new_new(cls, *args, **kwargs):
116            instance = old_new(cls, *args, **kwargs)
117            Santa.instance.children[id(instance)] = 0
118            Santa.instance.kids_by_id[id(instance)] = instance
119            return instance
120
121        new_class.__new__ = new_new
122
123        return new_class
124
125    @staticmethod
126    def bad_kid_checker(func):
127        def wrapper(self, *args, **kwargs):
128            try:
129                return func(self, *args, **kwargs)
130            except:
131                Santa.instance.blacklist.add(id(self))
132                raise
133        return wrapper

.............F......
======================================================================
FAIL: test_xmass_naughty (test.TestSanta.test_xmass_naughty)
Test a Christmas with naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 229, in test_xmass_naughty
self.assertEqual(kid3.SECRET_PRESENT, 'sirenie')
AssertionError: None != 'sirenie'

----------------------------------------------------------------------
Ran 20 tests in 0.024s

FAILED (failures=1)

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