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

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

4 точки общо

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

  1from functools import reduce
  2from copy import copy, deepcopy
  3
  4class Potion:
  5    def __init__(self, effects: dict, duration: int):
  6        self.effects = effects
  7        self.duration = duration
  8        self.used_effects = set()
  9        self.intensity = dict.fromkeys(effects, 1)
 10        self.used_in_the_bigger_picture = False
 11        self.applied = False
 12
 13    def __getattr__(self, attr):
 14        
 15        if attr in self.effects:
 16            if attr in self.used_effects:
 17                raise TypeError("Effect is depleted.")
 18            else:
 19                self.used_effects.add(attr)
 20                intensity = self.intensity[attr]
 21                self.intensity[attr] = 0
 22                return self.apply_intensity(self.effects[attr], intensity)
 23        else:
 24            raise AttributeError("Effect not found.")
 25
 26    def apply_intensity(self, effect, intensity):
 27        def potion_effect(target):
 28            for _ in range(intensity):
 29                effect(target)
 30        return potion_effect
 31
 32
 33    def copy(self):
 34        new = Potion(deepcopy(self.effects), self.duration)
 35        new.intensity = deepcopy(self.intensity)
 36        new.used_in_the_bigger_picture = False
 37        new.used_effects = deepcopy(self.used_effect)
 38        return new
 39
 40    def __mul__(self, number):
 41        if self.used_in_the_bigger_picture:
 42            raise TypeError("Potion is now part of something bigger than itself.")
 43        self.used_in_the_bigger_picture = True
 44
 45
 46        if number > 1:
 47            self._potenciirane(number)
 48        elif number > 0 and number < 1:
 49            self._razrejdane(number)
 50
 51        return self.copy()
 52
 53    def _potenciirane(self, times):
 54        
 55        for effect in self.effects:
 56            self.intensity[effect] *= times
 57        return self
 58
 59    def _razrejdane(self, percent):
 60        for effect in self.effects:
 61            self.intensity[effect] = int(self.intensity[effect] * percent) + 1 * (self.intensity[effect] * percent - int(self.intensity[effect] * percent) > 0.5)
 62        return self.copy()
 63
 64    def __add__(self, other_potion):
 65        if self.used_in_the_bigger_picture or other_potion.used_in_the_bigger_picture:
 66            raise TypeError("Potion is now part of something bigger than itself.")
 67        self.used_in_the_bigger_picture = True
 68        other_potion.used_in_the_bigger_picture = True
 69
 70        if self.applied or self.applied:
 71            raise TypeError("Potion is depleted.")
 72
 73        self.duration = max(self.duration, other_potion.duration)
 74        self.used_effect = self.used_effects.union(other_potion.used_effects)
 75
 76        for other_potion_effect in other_potion.effects:
 77            if other_potion_effect in self.effects:
 78                self.intensity[other_potion_effect] += other_potion.intensity[other_potion_effect]
 79            else:
 80                self.effects[other_potion_effect] = other_potion.effects[other_potion_effect]
 81                self.intensity[other_potion_effect] = other_potion.intensity[other_potion_effect]
 82
 83        return self.copy()
 84    
 85    def __sub__(self, other_potion):
 86        if self.used_in_the_bigger_picture or other_potion.used_in_the_bigger_picture:
 87            raise TypeError("Potion is now part of something bigger than itself.")
 88        self.used_in_the_bigger_picture = True
 89        other_potion.used_in_the_bigger_picture = True
 90
 91        if self.applied or self.applied:
 92            raise TypeError("Potion is depleted.")
 93
 94        effects_to_remove = set()
 95        for effect_name in other_potion.effects:
 96            if effect_name not in self.effects:
 97                raise TypeError("No potion effect as the left potion.")
 98            if self.intensity[effect_name] >= other_potion.intensity[effect_name]:
 99                self.intensity[effect_name] = max(self.intensity[effect_name] - other_potion.intensity[effect_name], 0)
100                if self.intensity[effect_name] == 0:
101                    effects_to_remove.add(effect_name)
102
103        for effect_name in effects_to_remove:
104            self.effects.pop(effect_name)
105            self.intensity.pop(effect_name)
106
107        self.duration = other_potion.duration
108        return self.copy()
109    
110    def __truediv__(self, divisor):
111
112        if self.used_in_the_bigger_picture:
113            raise TypeError("Potion is now part of something bigger than itself.")
114        self.used_in_the_bigger_picture = True
115
116        for effect in self.intensity:
117            self.intensity[effect] = round(self.intensity[effect] / divisor)
118
119        resulting_pots = []
120        for _ in range(divisor):
121            resulting_pots.append(self.copy())
122
123        return resulting_pots
124
125    def __eq__(self, other):
126        if not set(self.effects.keys()) == set(other.effects.keys()):
127            return False
128        
129        for effect in self.intensity:
130            if self.intensity[effect] != other.intensity[effect]:
131                return False
132            
133        return True
134
135    def __lt__(self, other):
136        return other > self
137
138    def __gt__(self, other):
139        
140        total_intensity = 0
141        for effect in self.intensity:
142            total_intensity += self.intensity[effect]
143
144        for effect in other.intensity:
145            total_intensity -= other.intensity[effect]
146
147        return total_intensity > 0
148
149
150
151class ГоспожатаПоХимия:
152    
153    def __init__(self):
154        self.targets = []
155        self.app_potions = {} 
156
157    def apply(self, target, potion):
158        self.targets.append(target)
159        # self.app_potions[]
160
161        if potion.used_in_the_bigger_picture:
162            raise TypeError("Potion is now part of something bigger than itself.")
163
164        if potion.applied or len(potion.used_effects) == len(potion.effects.keys()):
165            raise TypeError("Potion is depleted.")
166        potion.applied = True 
167
168        list_order = []
169        dict_order = {}
170
171        for effect in potion.effects:
172            list_order.append(sum(map(ord, effect)))
173            dict_order[sum(map(ord, effect))] = effect
174
175        list_order.sort()
176        list_order = list_order[::-1]
177
178        for order in list_order:
179            try:
180                potion.__getattr__(dict_order[order])(target)
181            except TypeError:
182                continue
183
184    def tick(self):
185        for target in self.targets:
186            target.duration = max(0, target.duration - 1)

...EE..FEEEEE.E.EEEE
======================================================================
ERROR: test_equal (test.TestPotionComparison)
Test equality of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 296, in test_equal
potion3 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
File "/tmp/solution.py", line 51, in __mul__
return self.copy()
File "/tmp/solution.py", line 37, in copy
new.used_effects = deepcopy(self.used_effect)
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError("Effect not found.")
AttributeError: Effect not found.

======================================================================
ERROR: test_superbness (test.TestPotionComparison)
Test superbness of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 316, in test_superbness
potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
File "/tmp/solution.py", line 51, in __mul__
return self.copy()
File "/tmp/solution.py", line 37, in copy
new.used_effects = deepcopy(self.used_effect)
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError("Effect not found.")
AttributeError: Effect not found.

======================================================================
ERROR: test_dilution (test.TestPotionOperations)
Test dilution of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 118, in test_dilution
half_potion = base_potion * 0.5
File "/tmp/solution.py", line 49, in __mul__
self._razrejdane(number)
File "/tmp/solution.py", line 62, in _razrejdane
return self.copy()
File "/tmp/solution.py", line 37, in copy
new.used_effects = deepcopy(self.used_effect)
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError("Effect not found.")
AttributeError: Effect not found.

======================================================================
ERROR: test_potentiation (test.TestPotionOperations)
Test potentiation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 110, in test_potentiation
potion = potion * 3
File "/tmp/solution.py", line 51, in __mul__
return self.copy()
File "/tmp/solution.py", line 37, in copy
new.used_effects = deepcopy(self.used_effect)
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError("Effect not found.")
AttributeError: Effect not found.

======================================================================
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 108, in __sub__
return self.copy()
File "/tmp/solution.py", line 37, in copy
new.used_effects = deepcopy(self.used_effect)
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError("Effect not found.")
AttributeError: Effect not found.

======================================================================
ERROR: test_separation (test.TestPotionOperations)
Test separation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 212, in test_separation
potion = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 9
File "/tmp/solution.py", line 51, in __mul__
return self.copy()
File "/tmp/solution.py", line 37, in copy
new.used_effects = deepcopy(self.used_effect)
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError("Effect not found.")
AttributeError: Effect not found.

======================================================================
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 383, in test_applying_depleted_potion
potion = potion * 2
File "/tmp/solution.py", line 51, in __mul__
return self.copy()
File "/tmp/solution.py", line 37, in copy
new.used_effects = deepcopy(self.used_effect)
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError("Effect not found.")
AttributeError: Effect not found.

======================================================================
ERROR: test_applying_order (test.TestГоспожатаПоХимия)
Test applying order of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 407, in test_applying_order
self._target = copy.deepcopy(self._target)
AttributeError: 'function' object has no attribute 'deepcopy'

======================================================================
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 426, in test_ticking_immutable
self._dimitrichka.tick()
File "/tmp/solution.py", line 186, in tick
target.duration = max(0, target.duration - 1)
AttributeError: 'Target' object has no attribute 'duration'

======================================================================
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 457, in test_ticking_multiple_potions
self._dimitrichka.tick()
File "/tmp/solution.py", line 186, in tick
target.duration = max(0, target.duration - 1)
AttributeError: 'Target' object has no attribute 'duration'

======================================================================
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 479, in test_ticking_multiple_targets
potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
File "/tmp/solution.py", line 51, in __mul__
return self.copy()
File "/tmp/solution.py", line 37, in copy
new.used_effects = deepcopy(self.used_effect)
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError("Effect not found.")
AttributeError: Effect not found.

======================================================================
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 443, in test_ticking_mutable
self._dimitrichka.tick()
File "/tmp/solution.py", line 186, in tick
target.duration = max(0, target.duration - 1)
AttributeError: 'Target' object has no attribute 'duration'

======================================================================
FAIL: test_deprecation (test.TestPotionOperations)
Test deprecation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 257, in test_deprecation
with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
AssertionError: TypeError not raised

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

FAILED (failures=1, errors=12)

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

Масово смятам за празните редове за излишни, then again, PEP8 не заема супер стриктна позиция: ``` Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations). Use blank lines in functions, sparingly, to indicate logical sections. ```
История
Това решение има само една версия.