Домашни > Работилница за отвари! > Решения > Решението на Десислава Белчева

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

2 точки общо

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

 1class Potion:
 2    def __init__(self, effects, duration):
 3        self._effects = {name: (func, 1) for name, func in effects.items()}
 4        self._duration = duration
 5        self._is_used = False
 6        self._is_depleted = False
 7
 8    def _call_effect(self, effect_name, target):
 9        if self._is_used or self._is_depleted:
10            raise TypeError("Potion is now part of something bigger than itself.")
11        func, intensity = self._effects.get(effect_name, (None, 0))
12        if intensity == 0:
13            raise TypeError("Effect is depleted.")
14        for _ in range(intensity):
15            func(target)
16        self._effects[effect_name] = (func, 0)
17        self._is_depleted = all(intensity == 0 for _, intensity in self._effects.values())
18
19    def __getattr__(self, name):
20        if name in self._effects:
21            return lambda target: self._call_effect(name, target)
22        raise TypeError("Effect is depleted.")
23
24    def __add__(self, other):
25        if self._is_used or other._is_used:
26            raise TypeError("Potion is now part of something bigger than itself.")
27        new_effects = {}
28        for name, (func, intensity) in self._effects.items():
29            new_intensity = intensity + other._effects.get(name, (None, 0))[1]
30            new_effects[name] = (func, new_intensity)
31        for name, (func, intensity) in other._effects.items():
32            if name not in new_effects:
33                new_effects[name] = (func, intensity)
34        self._is_used = True
35        other._is_used = True
36        return Potion(new_effects, max(self._duration, other._duration))
37
38    def __mul__(self, num):
39        if self._is_used:
40            raise TypeError("Potion is now part of something bigger than itself.")
41        new_effects = {name: (func, max(0, round(intensity * num)))
42                          for name, (func, intensity) in self._effects.items()}
43        self._is_used = True
44        return Potion(new_effects, self._duration)
45
46    def __sub__(self, other):
47        if self._is_used or other._is_used:
48            raise TypeError("Potion is now part of something bigger than itself.")
49        new_effects = {}
50        for name, (func, intensity) in self._effects.items():
51            new_intensity = max(0, intensity - other._effects.get(name, (None, 0))[1])
52            if new_intensity > 0:
53                new_effects[name] = (func, new_intensity)
54        self._is_used = True
55        other._is_used = True
56        return Potion(new_effects, self._duration)
57
58    def __truediv__(self, num):
59        if self._is_used:
60            raise TypeError("Potion is now part of something bigger than itself.")
61        new_effects = {name: (func, max(0, intensity / num))
62                           for name, (func, intensity) in self._effects.items()}
63        self._is_used = True
64        return [Potion(new_effects, self._duration) for _ in range(num)]
65
66    def __eq__(self, other):
67        return self._effects == other._effects
68
69    def __gt__(self, other):
70        return sum(intensity for _, intensity in self._effects.values()) > \
71               sum(intensity for _, intensity in other._effects.values())
72
73    def __lt__(self, other):
74        return sum(intensity for _, intensity in self._effects.values()) < \
75               sum(intensity for _, intensity in other._effects.values())
76
77
78class ГоспожатаПоХимия:
79    def __init__(self):
80        self._time = 0
81        self._applied_potions = []
82
83    def apply(self, target, potion):
84        if potion._is_used or potion._is_depleted:
85            raise TypeError("Potion is depleted.")
86        sorted_effects = sorted(potion._effects.items(), key=lambda x: sum(ord(s) for s in x[0]))
87        for name, (func, intensity) in sorted_effects:
88            for _ in range(intensity):
89                func(target)
90        potion._is_depleted = True
91        self._applied_potions.append((potion, self._time + potion._duration))
92
93    def tick(self):
94        self._time += 1
95        for potion, end_time in self._applied_potions:
96            if self._time >= end_time:
97                potion._is_depleted = True

.F.FFEE.EEEEF.F.EFEF
======================================================================
ERROR: test_combination_no_overlap (test.TestPotionOperations)
Test combining potions with no overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 94, in test_combination_no_overlap
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable

======================================================================
ERROR: test_combination_with_overlap (test.TestPotionOperations)
Test combining potions with overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 104, in test_combination_with_overlap
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable

======================================================================
ERROR: test_dilution (test.TestPotionOperations)
Test dilution of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 119, in test_dilution
half_potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable

======================================================================
ERROR: test_potentiation (test.TestPotionOperations)
Test potentiation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 111, in test_potentiation
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable

======================================================================
ERROR: test_purification (test.TestPotionOperations)
Test purification of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 166, in test_purification
potion.float_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable

======================================================================
ERROR: test_separation (test.TestPotionOperations)
Test separation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 214, in test_separation
potion1.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable

======================================================================
ERROR: test_ticking_immutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with immutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 424, in test_ticking_immutable
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 89, in apply
func(target)
TypeError: 'tuple' object is not callable

======================================================================
ERROR: test_ticking_multiple_targets (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 485, in test_ticking_multiple_targets
self._dimitrichka.apply(target1, potion1)
File "/tmp/solution.py", line 89, in apply
func(target)
TypeError: 'tuple' object is not callable

======================================================================
FAIL: test_depletion (test.TestBasicPotion)
Test depletion of a potion effect.
----------------------------------------------------------------------
TypeError: Potion is now part of something bigger than itself.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/tmp/test.py", line 78, in test_depletion
with self.assertRaisesRegex(TypeError, 'Effect is depleted\.'):
AssertionError: "Effect is depleted\." does not match "Potion is now part of something bigger than itself."

======================================================================
FAIL: test_equal (test.TestPotionComparison)
Test equality of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 292, in test_equal
self.assertEqual(potion1 + potion2, potion3)
AssertionError: <solution.Potion object at 0x7fa4085570a0> != <solution.Potion object at 0x7fa408557190>

======================================================================
FAIL: test_superbness (test.TestPotionComparison)
Test superbness of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 317, in test_superbness
self.assertLess(potion1, potion2)
AssertionError: <solution.Potion object at 0x7fa408557190> not less than <solution.Potion object at 0x7fa4085571c0>

======================================================================
FAIL: test_applying_depleted_potion (test.TestГоспожатаПоХимия)
Test applying a depleted potion or a potion that was used in a reaction.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 382, in test_applying_depleted_potion
with self.assertRaisesRegex(TypeError, 'Potion is depleted\.'):
AssertionError: TypeError not raised

======================================================================
FAIL: test_applying_order (test.TestГоспожатаПоХимия)
Test applying order of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 405, in test_applying_order
self.assertEqual(self._target.int_attr, 12)
AssertionError: 14 != 12

======================================================================
FAIL: test_ticking_multiple_potions (test.TestГоспожатаПоХимия)
Test ticking after applying multiple potions which affect the same attribute.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 458, in test_ticking_multiple_potions
self.assertEqual(self._target.int_attr, 50)
AssertionError: 500 != 50

======================================================================
FAIL: test_ticking_mutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 444, in test_ticking_mutable
self.assertEqual(self._target.int_attr, 5)
AssertionError: 50 != 5

----------------------------------------------------------------------
Ran 20 tests in 0.002s

FAILED (failures=7, errors=8)

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