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)
06.12.2023 09:24
06.12.2023 09:32