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

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

3 точки общо

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

  1applied_effects = set()
  2depleted_potions = set()
  3
  4
  5class Potion:
  6    def __init__(self, effects, duration):
  7        self.effects = effects
  8        self.duration = duration
  9        self.intensity = {effect: 1 for effect in effects}
 10        self.used = False
 11        self.depleted = False
 12        
 13    def __getattr__(self, effect):
 14        if self in depleted_potions:
 15            raise TypeError("Potion is depleted.") 
 16        self.depleted = True 
 17        if self.used:
 18            raise TypeError("Potion is now part of something bigger than itself.") 
 19        if effect not in self.effects:
 20            raise AttributeError
 21        def effect_wrapper(target):
 22            self.apply_effect(effect, target)
 23        return effect_wrapper
 24    
 25    def __hash__(self):
 26        effects_tuple = tuple(sorted(self.effects.items()))
 27        return hash((effects_tuple, frozenset(self.intensity.items())))
 28   
 29    def apply_effect(self, effect, target):
 30        if effect in applied_effects:
 31            raise TypeError("Effect is depleted.") 
 32        applied_effects.add(effect)
 33        for _ in range(self.intensity[effect]):
 34            self.effects[effect](target)
 35        self.intensity[effect] = 0  
 36    
 37    def __add__(self, other):
 38        if self.depleted or other.depleted:
 39            raise TypeError("Potion is depleted.") 
 40        if self.used or other.used:
 41            raise TypeError("Potion is now part of something bigger than itself.")
 42        combined_effects = {**self.effects, **other.effects}
 43        combined_duration = max(self.duration, other.duration)
 44        combined_potion = Potion(combined_effects, combined_duration)
 45        self.used = True
 46        other.used = True 
 47        combined_potion.intensity = {effect: self.intensity.get(effect, 0) + other.intensity.get(effect, 0) for effect in combined_effects}
 48        return combined_potion
 49    
 50    def __mul__(self, factor):
 51        if self.depleted:
 52            raise TypeError("Potion is depleted.") 
 53        if self.used:
 54            raise TypeError("Potion is now part of something bigger than itself.")
 55        self.used = True 
 56        new_potion = Potion(self.effects, self.duration)
 57        new_potion.intensity = {effect: self.intensity[effect] * factor for effect in self.effects}
 58        for effect, value in new_potion.intensity.items():
 59            if isinstance(value, float):
 60                integer = int(value)
 61                result = value - integer
 62                if result <= 0.5:
 63                    new_potion.intensity[effect] = integer
 64                else:
 65                    new_potion.intensity[effect] = round(value)
 66        return new_potion
 67    
 68    def __sub__(self, other):
 69        if self.depleted or other.depleted:
 70            raise TypeError("Potion is depleted.") 
 71        if self.used or other.used:
 72            raise TypeError("Potion is now part of something bigger than itself.")
 73        if set(other.effects.keys()).difference(self.effects.keys()):
 74            raise TypeError("Error!")
 75        effects_names = list(set(self.effects.keys()).difference(other.effects.keys()))
 76        effects_values = [self.intensity.get(effect, 0) for effect in effects_names]
 77        subtracted_effects_intensity = dict(zip(effects_names, effects_values))
 78        effects_to_remove = []
 79        for effect in self.effects:
 80            self_intensity = self.intensity.get(effect, 0)
 81            other_intensity = other.intensity.get(effect, 0)
 82            if effect in other.effects:
 83                subtracted_intensity = max(0, self_intensity - other_intensity)
 84                subtracted_effects_intensity[effect] = subtracted_intensity
 85            if subtracted_effects_intensity[effect] <= 0:
 86                effects_to_remove.append(effect)
 87        subtracted_effects = self.effects.copy()
 88        for effect in effects_to_remove:
 89            subtracted_effects.pop(effect)
 90            subtracted_effects_intensity.pop(effect)
 91        subtracted_duration = self.duration
 92        subtracted_potion = Potion(subtracted_effects, subtracted_duration)
 93        self.used = True 
 94        other.used = True 
 95        subtracted_potion.intensity = subtracted_effects_intensity
 96        return subtracted_potion
 97    
 98    def __truediv__(self, divisor):
 99        if self.depleted:
100            raise TypeError("Potion is depleted.") 
101        if self.used:
102            raise TypeError("Potion is now part of something bigger than itself.")
103        divided_intensity = {effect: self.intensity[effect] / divisor for effect in self.effects}
104        for effect, value in divided_intensity.items():
105            if isinstance(value, float):
106                integer = int(value)
107                result = value - integer
108                if result <= 0.5:
109                    divided_intensity[effect] = integer
110                else:
111                    divided_intensity[effect] = round(value)
112        divided_potions = []
113        divided_duration = self.duration
114        self.used = True 
115        for _ in range(divisor):
116            divided_potion = Potion(self.effects, divided_duration)
117            divided_potion.intensity = divided_intensity
118            divided_potions.append(divided_potion) 
119        return divided_potions 
120    
121    def __eq__(self, other):
122        return (self.effects == other.effects and self.intensity == other.intensity)
123    
124    def __lt__(self, other):
125        return sum(self.intensity.values()) < sum(other.intensity.values())
126
127    def __gt__(self, other):
128        return sum(self.intensity.values()) > sum(other.intensity.values())
129    
130
131class ГоспожатаПоХимия:
132    def __init__(self):
133        self.applied_potions = []
134    
135    def apply(self, target, potion):  
136        if potion.depleted or potion in self.applied_potions:
137            raise TypeError("Potion is depleted.")
138        if potion.used:
139            raise TypeError("Potion is now part of something bigger than itself.")
140        self.target = target
141        original_state = self.save_original_state(target)
142        ascii_dict = {key: sum(ord(char) for char in key) for key in potion.effects.keys()}
143        sorted_result = dict(sorted(ascii_dict.items(), key=lambda item: item[1], reverse=True)) 
144        changes = {} 
145        for effect_name in sorted_result:
146            if effect_name in applied_effects: 
147                raise TypeError("Effect is depleted.") 
148            pre_apply_state = self.save_original_state(target)
149            potion.effects[effect_name](target)
150            post_apply_state = self.save_original_state(target)
151            effect_changes = {attr_name: post_apply_state[attr_name] - pre_apply_state[attr_name] for attr_name in post_apply_state}
152            changes[effect_name] = effect_changes
153        potion.original_state = original_state.copy()
154        potion.changes = changes  
155        depleted_potions.add(potion) 
156        self.applied_potions.append(potion)
157        potion.depleted = True
158        potion.duration -= 1
159
160    def tick(self):
161        new_applied_potions = []
162        for potion in self.applied_potions:
163            if potion.duration > 0:
164                potion.duration -= 1
165                new_applied_potions.append(potion)
166            else:
167                for effect_changes in potion.changes.values():
168                    for attr_name, changed_value in effect_changes.items():
169                        current_value = getattr(self.target, attr_name, 0)
170                        setattr(self.target, attr_name, current_value - changed_value)
171        self.applied_potions = new_applied_potions
172    def save_original_state(self, target):
173        return {attr_name: getattr(target, attr_name) for attr_name in dir(target) if not attr_name.startswith("_")}

.E...EE.EEEEEEEEEEEE
======================================================================
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)
File "/tmp/solution.py", line 22, in effect_wrapper
self.apply_effect(effect, target)
File "/tmp/solution.py", line 31, in apply_effect
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 22, in effect_wrapper
self.apply_effect(effect, target)
File "/tmp/solution.py", line 31, in apply_effect
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 22, in effect_wrapper
self.apply_effect(effect, target)
File "/tmp/solution.py", line 31, in apply_effect
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 22, in effect_wrapper
self.apply_effect(effect, target)
File "/tmp/solution.py", line 31, in apply_effect
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 22, in effect_wrapper
self.apply_effect(effect, target)
File "/tmp/solution.py", line 31, in apply_effect
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 22, in effect_wrapper
self.apply_effect(effect, target)
File "/tmp/solution.py", line 31, in apply_effect
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 22, in effect_wrapper
self.apply_effect(effect, target)
File "/tmp/solution.py", line 31, in apply_effect
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
ERROR: 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 379, in test_applying_depleted_potion
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 147, in apply
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
ERROR: test_applying_normal_case (test.TestГоспожатаПоХимия)
Test applying a normal potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 350, in test_applying_normal_case
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 147, in apply
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
ERROR: test_applying_order (test.TestГоспожатаПоХимия)
Test applying order of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 404, in test_applying_order
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 151, in apply
effect_changes = {attr_name: post_apply_state[attr_name] - pre_apply_state[attr_name] for attr_name in post_apply_state}
File "/tmp/solution.py", line 151, in <dictcomp>
effect_changes = {attr_name: post_apply_state[attr_name] - pre_apply_state[attr_name] for attr_name in post_apply_state}
TypeError: unsupported operand type(s) for -: 'dict' and 'dict'

======================================================================
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)
File "/tmp/solution.py", line 22, in effect_wrapper
self.apply_effect(effect, target)
File "/tmp/solution.py", line 31, in apply_effect
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 147, in apply
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 454, in test_ticking_multiple_potions
self._dimitrichka.apply(self._target, potion1)
File "/tmp/solution.py", line 147, in apply
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
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 147, in apply
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

======================================================================
ERROR: test_ticking_mutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 438, in test_ticking_mutable
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 147, in apply
raise TypeError("Effect is depleted.")
TypeError: Effect is depleted.

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

FAILED (errors=15)

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