Домашни > Работилница за отвари! > Решения > Решението на Мария Кукова

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

1 точки общо

2 успешни теста
18 неуспешни теста
Код

 1class Potion:
 2    def __init__(self, effects, duration):
 3        self.effects = effects
 4        self.duration = duration
 5        self.applied_effects = set()
 6
 7    def apply_effect(self, effect, target, intensity=1):
 8        if effect in self.applied_effects:
 9            raise TypeError("Effect is depleted.")
10
11        for _ in range(intensity):
12            self.effects[effect](target)
13
14        self.applied_effects.add(effect)
15
16    def apply(self, target):
17        for effect in self.effects:
18            self.apply_effect(effect, target)
19
20    def __add__(self, other):
21        combined_effects = {effect: lambda target: self.effects[effect](target) for effect in self.effects}
22        combined_effects.update({effect: lambda target: other.effects[effect](target) for effect in other.effects})
23
24        combined_duration = max(self.duration, other.duration)
25
26        return Potion(combined_effects, combined_duration)
27
28    def __mul__(self, factor):
29        multiplied_effects = {effect: lambda target, factor=factor: self.effects[effect](target) for effect in
30                              self.effects}
31        multiplied_duration = self.duration
32
33        return Potion(multiplied_effects, multiplied_duration)
34
35    def __truediv__(self, divisor):
36        diluted_effects = {effect: lambda target, divisor=divisor: self.effects[effect](target, intensity=divisor) for
37                           effect in self.effects}
38        diluted_duration = self.duration
39
40        return Potion(diluted_effects, diluted_duration)
41
42    def __sub__(self, other):
43        if not all(effect in self.effects for effect in other.effects):
44            raise TypeError("Mismatched effects for subtraction.")
45
46        subtracted_effects = {
47            effect: lambda target, intensity=self.effects[effect], other_intensity=other.effects[effect]: intensity(
48                target, intensity=-other_intensity) for effect in self.effects}
49        subtracted_duration = self.duration
50
51        return Potion(subtracted_effects, subtracted_duration)
52
53    def __eq__(self, other):
54        return all(self.effects[effect] == other.effects[effect] for effect in self.effects)
55
56    def __lt__(self, other):
57        return sum(self.effects[effect] for effect in self.effects) < sum(
58            other.effects[effect] for effect in other.effects)
59
60    def __gt__(self, other):
61        return sum(self.effects[effect] for effect in self.effects) > sum(
62            other.effects[effect] for effect in other.effects)
63
64    def __repr__(self):
65        return f"Potion(effects={self.effects}, duration={self.duration})"
66
67
68class ГоспожатаПоХимия:
69    def __init__(self):
70        self.active_potions = []
71
72    def apply(self, target, potion):
73        if not self.is_potion_depleted(potion):
74            self.process_effects(target, potion)
75
76    def process_effects(self, target, potion):
77        effects_sorted = sorted(potion.effects.keys(), key=lambda effect: sum(map(ord, effect)))
78        for effect in effects_sorted:
79            if effect not in potion.applied_effects:
80                potion.apply_effect(effect, target)
81
82        self.active_potions.append(potion)
83
84    def is_potion_depleted(self, potion):
85        if potion in self.active_potions:
86            raise TypeError("Potion is now part of something bigger than itself.")
87
88        return potion.applied_effects == potion.effects.keys()
89
90    def tick(self):
91        for potion in self.active_potions:
92            potion.duration -= 1
93            if potion.duration == 0:
94                self.active_potions.remove(potion)

EE.FEEEEEEEEF.FEFEFF
======================================================================
ERROR: test_applying (test.TestBasicPotion)
Test applying a potion to a target.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 63, in test_applying
potion.int_attr_fun(self._target)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'

======================================================================
ERROR: test_depletion (test.TestBasicPotion)
Test depletion of a potion effect.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 76, in test_depletion
potion.int_attr_fun(self._target)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'

======================================================================
ERROR: 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)
File "/usr/lib/python3.10/unittest/case.py", line 1230, in assertLess
if not a < b:
File "/tmp/solution.py", line 57, in __lt__
return sum(self.effects[effect] for effect in self.effects) < sum(
TypeError: unsupported operand type(s) for +: 'int' and 'function'

======================================================================
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)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'

======================================================================
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)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'

======================================================================
ERROR: test_deprecation (test.TestPotionOperations)
Test deprecation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 258, in test_deprecation
potion1.int_attr_fun(self._target)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'

======================================================================
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)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'

======================================================================
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)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'

======================================================================
ERROR: test_purification (test.TestPotionOperations)
Test purification of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 165, in test_purification
potion = potion1 - potion2
File "/tmp/solution.py", line 46, in __sub__
subtracted_effects = {
File "/tmp/solution.py", line 47, in <dictcomp>
effect: lambda target, intensity=self.effects[effect], other_intensity=other.effects[effect]: intensity(
KeyError: 'float_attr_fun'

======================================================================
ERROR: test_separation (test.TestPotionOperations)
Test separation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 213, in test_separation
potion1, potion2, potion3 = potion / 3
TypeError: cannot unpack non-iterable Potion object

======================================================================
ERROR: test_applying_part_of_potion (test.TestГоспожатаПоХимия)
Test applying only a part of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 364, in test_applying_part_of_potion
potion.int_attr_fun(temp_target)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'

======================================================================
ERROR: 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 455, in test_ticking_multiple_potions
self._dimitrichka.apply(self._target, potion2)
File "/tmp/solution.py", line 73, in apply
if not self.is_potion_depleted(potion):
File "/tmp/solution.py", line 86, in is_potion_depleted
raise TypeError("Potion is now part of something bigger than itself.")
TypeError: 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: Potio[32 chars]tion Potion.__add__.<locals>.<dictcomp>.<lambd[122 chars]on=1) != Potio[32 chars]tion int_attr_fun at 0x7f384b49e950>, 'float_a[62 chars]on=1)

======================================================================
FAIL: test_applying_depleted_potion (test.TestГоспожатаПоХимия)
Test applying a depleted potion or a potion that was used in a reaction.
----------------------------------------------------------------------
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 380, in test_applying_depleted_potion
with self.assertRaisesRegex(TypeError, 'Potion is depleted\.'):
AssertionError: "Potion is depleted\." does not match "Potion is now part of something bigger than itself."

======================================================================
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_immutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with immutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 425, in test_ticking_immutable
self.assertEqual(self._target.int_attr, 500)
AssertionError: 50 != 500

======================================================================
FAIL: 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 487, in test_ticking_multiple_targets
self.assertEqual(target1.int_attr, 500)
AssertionError: 50 != 500

======================================================================
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=6, errors=12)

Дискусия
Виктор Бечев
06.12.2023 10:00

Като изключим тук-таме прекалено либералната (по мое мнение) употреба на празни редове - нямам стилистични забележки. Но уви, липсва основния building block на заданието - достъпването на ефектите като callables.
История
Това решение има само една версия.