Домашни > Великденско домашно > Решения > Решението на Стефан Иванов

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

6 точки общо

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

  1class Egg:
  2    def __init__(self):
  3        self._layers = []
  4        self._painted = 0.0
  5
  6        self._top_broken = False
  7        self._bottom_broken = False
  8
  9        self._tournament = None
 10        self._registration_name = None
 11
 12    @staticmethod
 13    def _pigment_value(hex_color):
 14        hex_color = hex_color.upper()
 15
 16        red = int(hex_color[0:2], 16)
 17        green = int(hex_color[2:4], 16)
 18        blue = int(hex_color[4:6], 16)
 19
 20        return red + green + blue
 21
 22    def paint(self, *pairs):
 23        total_to_add = 0.0
 24        for _, percentage in pairs:
 25            total_to_add += percentage
 26
 27        if self._painted + total_to_add > 100.0:
 28            raise ValueError
 29
 30        current = self._painted
 31        new_layers = []
 32
 33        for hex_color, percentage in pairs:
 34            pigment = self._pigment_value(hex_color)
 35            start = current
 36            end = current + percentage
 37
 38            new_layers.append((start, end, pigment))
 39            current = end
 40
 41        self._layers.extend(new_layers)
 42        self._painted = current
 43
 44    def _side_stats(self, side):
 45        if side == "top":
 46            side_start = 0.0
 47            side_end = 50.0
 48        else:
 49            side_start = 50.0
 50            side_end = 100.0
 51
 52        strength = 0.0
 53        coverage = 0.0
 54
 55        for start, end, pigment in self._layers:
 56            overlap_start = max(start, side_start)
 57            overlap_end = min(end, side_end)
 58
 59            if overlap_start < overlap_end:
 60                overlap = overlap_end - overlap_start
 61                coverage += overlap
 62                strength += (overlap / 50.0) * pigment
 63
 64        return strength, coverage
 65
 66    def _record_if_needed(self, other, side, winner):
 67        if self._tournament is not None and self._tournament is other._tournament:
 68            self._tournament._record_battle(self, other, side, winner)
 69
 70    def _fight(self, other, side):
 71        if not isinstance(other, Egg):
 72            return NotImplemented
 73
 74        if side == "top":
 75            if self._top_broken or other._top_broken:
 76                raise TypeError
 77        else:
 78            if self._bottom_broken or other._bottom_broken:
 79                raise TypeError
 80
 81        my_strength, my_coverage = self._side_stats(side)
 82        other_strength, other_coverage = other._side_stats(side)
 83
 84        my_score = (my_strength, my_coverage)
 85        other_score = (other_strength, other_coverage)
 86
 87        if my_score > other_score:
 88            winner = self
 89            loser = other
 90        else:
 91            winner = other
 92            loser = self
 93
 94        if side == "top":
 95            loser._top_broken = True
 96        else:
 97            loser._bottom_broken = True
 98
 99        self._record_if_needed(other, side, winner)
100        return winner
101
102    def __mul__(self, other):
103        return self._fight(other, "top")
104
105    def __matmul__(self, other):
106        return self._fight(other, "bottom")
107
108
109class EggTournament:
110    def __init__(self):
111        self._eggs_by_name = {}
112        self._names_by_egg = {}
113        self._history = []
114        self._victories = {}
115
116    def register(self, egg, name):
117        if not isinstance(name, str) or not name.isidentifier():
118            raise ValueError("Invalid registration name")
119
120        if name in self._eggs_by_name:
121            raise ValueError(f"Egg with name {name} has already been registered")
122
123        if egg._tournament is not None:
124            raise ValueError("An egg cannot be registered in multiple tournaments")
125
126        self._eggs_by_name[name] = egg
127        self._names_by_egg[egg] = name
128        self._victories[egg] = 0
129
130        egg._tournament = self
131        egg._registration_name = name
132
133    def _record_battle(self, egg1, egg2, side, winner):
134        self._history.append((egg1, egg2, side, winner))
135        self._victories[winner] += 1
136
137    def __getitem__(self, item):
138        if isinstance(item, tuple):
139            egg1, egg2, side = item
140        elif isinstance(item, slice):
141            egg1, egg2, side = item.start, item.stop, item.step
142        else:
143            raise KeyError
144
145        for first_egg, second_egg, battle_side, winner in self._history:
146            same_order = first_egg is egg1 and second_egg is egg2
147            reverse_order = first_egg is egg2 and second_egg is egg1
148
149            if battle_side == side and (same_order or reverse_order):
150                return winner
151
152        raise KeyError
153
154    def _ranking_groups(self):
155        grouped = {}
156
157        for egg, wins in self._victories.items():
158            if wins not in grouped:
159                grouped[wins] = set()
160
161            grouped[wins].add(egg)
162
163        sorted_wins = sorted(grouped.keys(), reverse=True)
164
165        position_to_eggs = {}
166        egg_to_position = {}
167
168        position = 1
169        for wins in sorted_wins:
170            eggs = grouped[wins]
171            position_to_eggs[position] = eggs
172
173            for egg in eggs:
174                egg_to_position[egg] = position
175
176            position += 1
177
178        return position_to_eggs, egg_to_position
179
180    def __rmatmul__(self, position):
181        position_to_eggs, _ = self._ranking_groups()
182
183        if position not in position_to_eggs:
184            raise IndexError
185
186        eggs = position_to_eggs[position]
187
188        if len(eggs) == 1:
189            return next(iter(eggs))
190
191        return eggs
192
193    def __getattr__(self, name):
194        if name not in self._eggs_by_name:
195            raise AttributeError("Apologies, there is no such egg registered")
196
197        egg = self._eggs_by_name[name]
198        _, egg_to_position = self._ranking_groups()
199
200        return {
201            "position": egg_to_position[egg],
202            "victories": self._victories[egg],
203        }
204
205    def __contains__(self, egg):
206        return egg in self._names_by_egg
207    

..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.002s

OK

Дискусия
Виктор Бечев
15.04.2026 14:00

Браво, чисто решение, с дребни проблеми.
История
Това решение има само една версия.