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

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

7 точки общо

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

  1import math
  2import copy
  3
  4def check_states(*potions):
  5    
  6    for potion in potions:
  7        if potion.mixed:
  8            raise TypeError("Potion is now part of something bigger than itself.")
  9        
 10        if potion.applied:
 11            raise TypeError("Potion is depleted.")
 12    
 13def set_is_part_true(effect):
 14    
 15    for name in effect.effect_dict.keys():
 16        effect.effect_dict[name].is_part_of_smth = True
 17        
 18class Effect:
 19    
 20    def __init__(self, name, function):
 21        self.name = name
 22        self.function = function
 23        self.intensity = 1
 24        self.used = False
 25        self.is_part_of_smth = False
 26        self.masa = sum(ord(char) for char in name)
 27        self.applied = False
 28    
 29    def __call__(self, args):
 30        if self.applied:
 31            raise TypeError("Potion is depleted.")
 32        elif self.used:
 33            raise TypeError("Effect is depleted.")
 34        elif self.is_part_of_smth:
 35            raise TypeError("Potion is now part of something bigger than itself.")
 36        for times in range(self.intensity):
 37            self.function(args)
 38        self.used = True
 39        
 40       
 41class Potion:
 42    
 43    def __init__(self, effects, duration):
 44        self.effect_dict = {}
 45        for name, func in effects.items():
 46            new_effect = Effect(name, func)
 47            self.effect_dict[name] = new_effect
 48            setattr(self, name, new_effect)
 49        self.duration = duration
 50        self.mixed = False
 51        self.applied = False
 52        
 53    def __eq__(self, other_potion):
 54        
 55        check_states(self, other_potion)
 56        
 57        if self.effect_dict.keys() != other_potion.effect_dict.keys():
 58            return False
 59        for name in self.effect_dict.keys():
 60           if (self.effect_dict[name].intensity != other_potion.effect_dict[name].intensity) and ((self.effect_dict[name].used and other_potion.effect_dict[name].used) or ((not self.effect_dict[name].used) and  (not other_potion.effect_dict[name].used))):
 61                return False
 62        
 63        return True
 64      
 65    def __gt__(self, other_potion):
 66        
 67        sum1 = sum(self.effect_dict[name].intensity for name in self.effect_dict if not self.effect_dict[name].used)
 68        sum2 = sum(other_potion.effect_dict[name].intensity for name in other_potion.effect_dict if not other_potion.effect_dict[name].used)
 69        
 70        return sum1 > sum2
 71        
 72    def __lt__(self, other_potion):
 73
 74        check_states(self, other_potion)
 75        
 76        sum1 = sum(self.effect_dict[name].intensity for name in self.effect_dict if not self.effect_dict[name].used)
 77        sum2 = sum(other_potion.effect_dict[name].intensity for name in other_potion.effect_dict if not other_potion.effect_dict[name].used)
 78            
 79        return sum1 < sum2
 80        
 81    def __truediv__(self, num):
 82        list_of_potions = []
 83        for i in range(num):
 84            list_of_potions.append(self*(1/num))
 85            self.mixed = False
 86        self.mixed = True
 87        return tuple(list_of_potions)
 88    
 89    def __mul__(self, num):
 90
 91        check_states(self)
 92        new_potion = copy.deepcopy(self)
 93        for effect in new_potion.effect_dict.values():
 94            effect.intensity *= num 
 95            if isinstance(effect.intensity, float):
 96                if effect.intensity - int(effect.intensity) <= 0.5:
 97                    effect.intensity = math.floor(effect.intensity)
 98                else:
 99                    effect.intensity = math.ceil(effect.intensity)
100        set_is_part_true(self)
101            
102        self.mixed = True
103        return new_potion   
104    
105    def __sub__(self, other_potion):
106
107        for name, func in other_potion.effect_dict.items():
108            if (name not in self.effect_dict) or (name in self.effect_dict and self.effect_dict[name].used):
109                raise TypeError("There is no such effect on the left side")
110
111        check_states(self, other_potion)
112            
113        new_effects = {}
114        new_pot = Potion(new_effects, self.duration)
115        for name, effect in self.effect_dict.items():
116            if name not in other_potion.effect_dict:
117                curr_effect = Effect(name, effect.function)
118                curr_effect.intensity = effect.intensity
119                curr_effect.used = effect.used 
120                new_pot.effect_dict[name] = curr_effect
121                setattr(new_pot, name, curr_effect)
122            elif name in other_potion.effect_dict and not other_potion.effect_dict[name].used:
123                curr_effect = Effect(name, effect.function)
124                curr_effect.intensity = effect.intensity - other_potion.effect_dict[name].intensity
125                if curr_effect.intensity <= 0:
126                    curr_effect.used = True
127                else:
128                    curr_effect.used = effect.used
129                new_pot.effect_dict[name] = curr_effect
130                setattr(new_pot, name, curr_effect)
131                
132        set_is_part_true(self)
133        set_is_part_true(other_potion)
134            
135        self.mixed = True
136        other_potion.mixed = True
137        return new_pot
138                
139    def __add__(self, other_potion):
140
141        check_states(self, other_potion)
142        
143        new_effects = {}
144        max_duration = max(self.duration, other_potion.duration)
145        new_potion = Potion(new_effects, max_duration)
146        for name, func in self.effect_dict.items():
147            new_effect = Effect(name, func.function)
148            new_effect.intensity = func.intensity
149            new_effect.used = func.used
150            new_potion.effect_dict[name] = new_effect
151            setattr(new_potion, name, new_effect)
152            
153        for key, value in other_potion.effect_dict.items():
154            if key in self.effect_dict:
155                new_potion.effect_dict[key].intensity += value.intensity
156            else:
157                new_effect = Effect(key, value.function)
158                new_effect.intensity = value.intensity
159                new_effect.used = value.used
160                new_potion.effect_dict[key] = new_effect
161                setattr(new_potion, key, new_effect)
162                
163        set_is_part_true(self)
164        set_is_part_true(other_potion)        
165            
166        self.mixed = True
167        other_potion.mixed = True
168        return new_potion
169       
170
171class ГоспожатаПоХимия:
172    
173    def __init__(self):
174        self.counterDuration = 0
175        self.list_of_targets = []
176    
177    def apply_potion(self, target, potion):
178        for effect in potion.effect_dict.values():
179                effect.function(target)
180    
181    def tick(self):
182        self.counterDuration += 1
183        for potion_in_list in self.list_of_targets:
184            print(potion_in_list[2].duration)
185            print(potion_in_list[1].size)
186            print(potion_in_list[0].size)
187            if potion_in_list[2].duration == self.counterDuration:
188                potion_in_list[1].__dict__ = potion_in_list[0].__dict__
189                self.list_of_targets.remove(potion_in_list)
190                for curr_list in self.list_of_targets:
191                    if id(curr_list[1]) == id(potion_in_list[1]):
192                        self.apply_potion(curr_list[1], curr_list[2])
193                
194            
195    def apply(self, target, potion):
196        
197        if potion.duration == 0:
198            return
199        
200        check_states(potion)
201        target_before_apply = copy.deepcopy(target)
202
203        potion.applied = True
204        items_list = [(key, value) for key, value in potion.effect_dict.items()]
205        sorted_list = sorted(items_list, key=lambda item: item[1].masa, reverse=True)
206        for effect in sorted_list:
207            if not effect[1].used:
208                for times in range(effect[1].intensity):
209                    effect[1].function(target)
210                effect[1].used = True
211                effect[1].applied = True
212                
213        self.list_of_targets.append([target_before_apply, target, potion])
214        self.list_of_targets = sorted(self.list_of_targets, key=lambda x: x[2].duration)

..........EE....E
Stdout:
2
E
Stdout:
1
E
Stdout:
1
E
Stdout:
1

======================================================================
ERROR: test_purification (test.TestPotionOperations)
Test purification of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 169, in test_purification
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 33, in __call__
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 218, in test_separation
potion2.int_attr_fun(self._target)
File "/tmp/solution.py", line 35, in __call__
raise TypeError("Potion is now part of something bigger than itself.")
TypeError: Potion is now part of something bigger than itself.

======================================================================
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 185, in tick
print(potion_in_list[1].size)
AttributeError: 'Target' object has no attribute 'size'

Stdout:
2

======================================================================
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 185, in tick
print(potion_in_list[1].size)
AttributeError: 'Target' object has no attribute 'size'

Stdout:
1

======================================================================
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 489, in test_ticking_multiple_targets
self._dimitrichka.tick()
File "/tmp/solution.py", line 185, in tick
print(potion_in_list[1].size)
AttributeError: 'Target' object has no attribute 'size'

Stdout:
1

======================================================================
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 185, in tick
print(potion_in_list[1].size)
AttributeError: 'Target' object has no attribute 'size'

Stdout:
1

----------------------------------------------------------------------
Ran 20 tests in 0.003s

FAILED (errors=6)

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