Домашни > Великденско домашно > Решения > Решението на Магдалена Дичева

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

5 точки общо

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

  1class Egg:
  2    def __init__(self):
  3        self._sum_percent = 0.0
  4        self._top_lost = False
  5        self._bottom_lost = False 
  6        self._painted_parts = []
  7        self._Egg_tournament = None
  8
  9    def paint(self, *parts):
 10        current_sum = self._sum_percent
 11        for part in parts:
 12            percent = part[1]
 13            current_sum += percent
 14        if current_sum > 100.0:
 15            raise ValueError("Cannot exceed 100%")
 16        for part in parts:
 17            hex_color = part[0]
 18            percent = part[1]
 19            self._painted_parts.append((hex_color.upper(), percent))
 20            self._sum_percent += percent
 21
 22    def _half_of_the_egg(self, top_or_bottom):
 23        if top_or_bottom:
 24            if self._top_lost:
 25                raise TypeError("This egg has already been defeated from the top side!")
 26            first, sec = 0.0, 50.0
 27        else:
 28            if self._bottom_lost:
 29                raise TypeError("This egg has already been defeated from the bottom side!")
 30            first, sec = 50.0, 100.0
 31        pigment_quantity = 0.0
 32        current_percentage = 0.0
 33        for hex_color, prc_of_part in self._painted_parts:
 34            first_part = current_percentage
 35            sec_part = current_percentage + prc_of_part
 36            current_percentage = sec_part
 37            first_overlap = max(first_part,first)
 38            sec_overlap = min(sec_part, sec)
 39            if sec_overlap > first_overlap:
 40                percent_overlap = sec_overlap - first_overlap
 41                r = int(hex_color[0:2], 16)
 42                g = int(hex_color[2:4], 16)
 43                b = int(hex_color[4:6], 16)
 44                paint_per_100p = r + g + b
 45                pigment_quantity += paint_per_100p * (percent_overlap / 100.0)
 46        return pigment_quantity
 47    
 48    def __mul__(self, other):
 49        
 50        if not isinstance(other, Egg):
 51            return NotImplemented
 52        left = self._half_of_the_egg(top_or_bottom=True)
 53        right = other._half_of_the_egg(top_or_bottom=True)
 54
 55        if left > right:
 56           winner = self
 57           loser = other
 58        else:
 59            winner = other
 60            loser = self
 61        loser._top_lost =True
 62
 63        if (
 64            self._Egg_tournament is not None and
 65            other._Egg_tournament is not None and 
 66            self._Egg_tournament == other._Egg_tournament
 67        ):
 68            self._Egg_tournament.Battles(self, other, "top", winner)
 69        
 70        return winner
 71    
 72    def __matmul__(self, other):
 73        
 74        if not isinstance(other, Egg):
 75            return NotImplemented
 76        left = self._half_of_the_egg(top_or_bottom=False)
 77        right = other._half_of_the_egg(top_or_bottom=False)
 78        if left > right:
 79            winner = self
 80            loser = other
 81        else:
 82            winner = other
 83            loser = self
 84        loser._bottom_lost =True
 85        if (
 86            self._Egg_tournament is not None and
 87            other._Egg_tournament is not None and 
 88            self._Egg_tournament == other._Egg_tournament
 89        ):
 90            self._Egg_tournament.Battles(self, other, "bottom", winner)
 91        return winner
 92
 93class EggTournament:
 94    def __init__(self):
 95        self.name_egg = {}
 96        self.egg_name = {}
 97        self.win = {}
 98        self.storage = {}
 99
100    def register(self, egg, name):
101        if not name.isidentifier():
102            raise ValueError("Invalid registration name")
103        if hasattr(egg, '_Egg_tournament') and egg._Egg_tournament is not None:
104            raise ValueError("An egg cannot be registered in multiple tournaments")
105        if name in self.name_egg:
106            raise ValueError(f"Egg with name {name} has already been registered")
107        self.name_egg[name] = egg
108        self.egg_name[egg] = name
109        self.win[egg] = 0
110        egg._Egg_tournament = self
111    
112    def Battles(self, egg1, egg2, side, winner):
113        key1 = id(egg1)
114        key2 = id(egg2)
115        if key1 < key2:
116            key = (key1, key2, side)
117        else:
118            key = (key2, key1, side)
119        self.storage[key] = winner
120        if winner in self.win:
121            self.win[winner] += 1
122        
123    def _normalize_eggs(self, egg1, egg2):
124        if id(egg1) < id(egg2):
125            return id(egg1), id(egg2)
126        return id(egg2), id(egg1)
127
128    def __getitem__(self, key):
129        if isinstance(key, tuple):
130            if len(key) != 3:
131                raise KeyError("Invalid key")
132            egg1, egg2, side = key
133        elif isinstance(key, slice):
134            egg1 = key.start
135            egg2 = key.stop
136            side = key.step
137        else:
138            raise KeyError("Invalid key")
139        if side not in ("top", "bottom"):
140            raise KeyError("Invalid side")
141        if egg1 not in self.win or egg2 not in self.win:
142            raise KeyError("not a valid registration")
143        key1, key2 = self._normalize_eggs(egg1, egg2)
144        key_tuple = (key1, key2, side)
145        if key_tuple not in self.storage:
146            raise KeyError("there is no battle between these eggs")
147        return self.storage[key_tuple]
148    
149    def __matmul__(self, position):
150        if not isinstance(position, int):
151            raise TypeError("Position must be an integer")
152        if position < 1:
153            raise IndexError("position must be >=1")
154        def get_wins(egg):
155            return self.win[egg]
156        sort_eggs = sorted(
157            self.win.keys(),
158            key=get_wins,
159            reverse=True
160        )
161        if position > len(sort_eggs):
162            raise IndexError("position is out of range")
163        winners = []
164        current_winners = None
165        current_group = []
166        for egg in sort_eggs:
167            winner = self.win[egg]
168            if winner != current_winners:
169                if current_group:
170                    winners.append(current_group)
171                current_winners = winner
172                current_group = [egg]
173            else:
174                current_group.append(egg)
175        if current_group:
176            winners.append(current_group)
177        
178        pos = 1
179        for group in winners:
180            if pos <= position < pos + len(group):
181                if len(group) == 1:
182                    return group[0]
183                else:
184                    return set(group)
185            pos += len(group)
186        raise IndexError("Invalid position")
187    
188    def __getattr__(self, name):
189        if name not in self.name_egg:
190            raise AttributeError("Apologies, there is no such egg registered")
191        egg = self.name_egg[name]
192        victories = self.win[egg]
193        def get_wins(e):
194            return self.win[e]
195        sorted_eggs = sorted(
196            self.win.keys(),
197            key=get_wins,
198            reverse=True
199        )
200        pos = 1
201        i = 0
202        while i < len(sorted_eggs):
203            current = self.win[sorted_eggs[i]]
204            count = 0
205            while i+count < len(sorted_eggs) and self.win[sorted_eggs[i + count]] == current:
206                count += 1
207            for j in range(count):
208                if sorted_eggs[i+j] == egg:
209                    return {"position": pos, "victories": victories}
210            pos += count
211            i += count
212
213        return {"position": pos, "victories": victories}
214    
215    def __contains__(self, item):
216        return item in self.win
217        

.....................F..E.............EEEE....
======================================================================
ERROR: test_collision_between_two_registered_eggs_is_recorded (test.TestEggTournament.test_collision_between_two_registered_eggs_is_recorded)
A collision between two registered eggs should be recorded in the tournament.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 373, in test_collision_between_two_registered_eggs_is_recorded
self.assertIs(1 @ tournament, first_egg)
~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for @: 'int' and 'EggTournament'

======================================================================
ERROR: test_ranking_missing_position_raises_index_error (test.TestEggTournament.test_ranking_missing_position_raises_index_error)
Looking up a missing ranking position should raise an IndexError.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 539, in test_ranking_missing_position_raises_index_error
_ = 4 @ tournament
~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for @: 'int' and 'EggTournament'

======================================================================
ERROR: test_ranking_tied_position_returns_set_of_eggs (test.TestEggTournament.test_ranking_tied_position_returns_set_of_eggs)
Looking up a tied ranking position should return a set of eggs.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 492, in test_ranking_tied_position_returns_set_of_eggs
self.assertEqual(1 @ tournament, {alpha, beta})
~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for @: 'int' and 'EggTournament'

======================================================================
ERROR: test_ranking_unique_position_returns_single_egg (test.TestEggTournament.test_ranking_unique_position_returns_single_egg)
Looking up a unique ranking position should return a single egg.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 478, in test_ranking_unique_position_returns_single_egg
self.assertIs(1 @ tournament, alpha)
~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for @: 'int' and 'EggTournament'

======================================================================
ERROR: test_ranking_uses_dense_ranking_without_skipping_places (test.TestEggTournament.test_ranking_uses_dense_ranking_without_skipping_places)
Looking up ranking positions should use dense ranking without skipping places.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 514, in test_ranking_uses_dense_ranking_without_skipping_places
self.assertIs(1 @ tournament, alpha)
~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for @: 'int' and 'EggTournament'

======================================================================
FAIL: test_unpainted_half_loses_to_half_painted_black (test.TestEgg.test_unpainted_half_loses_to_half_painted_black)
An unpainted half should lose to a half painted in black.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 205, in test_unpainted_half_loses_to_half_painted_black
self.assertIs(black_egg * unpainted_egg, black_egg)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: <solution.Egg object at 0x7c5b9b80d0f0> is not <solution.Egg object at 0x7c5b9b80cfa0>

----------------------------------------------------------------------
Ran 46 tests in 0.003s

FAILED (failures=1, errors=5)

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