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

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

6 точки общо

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

  1import keyword
  2
  3EPS = 1e-9
  4
  5class Egg:
  6    def __init__(self):
  7        self.segments = []
  8        self.covered = 0.0
  9        self.top_cracked = False
 10        self.bottom_cracked = False
 11        self.tournament = None
 12
 13    def paint(self, *pairs):
 14        sum_new_percentage = sum(percentage for _, percentage in pairs)
 15
 16        if self.covered + sum_new_percentage > 100.0 + EPS:
 17            raise ValueError("Egg cannot be overpainted")
 18
 19        for hex_color, percentage in pairs:
 20            self.segments.append((hex_color.upper(), percentage))
 21
 22        self.covered += sum_new_percentage
 23
 24    def _pigment_value(self, hex_color):
 25        r = int(hex_color[0:2], base=16)
 26        g = int(hex_color[2:4], base=16)
 27        b = int(hex_color[4:6], base=16)
 28        return r + g + b
 29
 30    def _strength(self, side):
 31        if side == "top":
 32            side_start = 0.0
 33            side_end = 50.0
 34        elif side == "bottom":
 35            side_start = 50.0
 36            side_end = 100.0
 37
 38        current_position = 0.0
 39        total_strength = 0.0
 40        has_paint = False
 41
 42        for hex_color, percentage in self.segments:
 43            segment_start = current_position
 44            segment_end = current_position + percentage
 45
 46            overlap_start = max(segment_start, side_start)
 47            overlap_end = min(segment_end, side_end)
 48
 49            if overlap_start < overlap_end:
 50                has_paint = True
 51                segment_portion = (overlap_end - overlap_start) / 50.0
 52                total_strength += self._pigment_value(hex_color) * segment_portion
 53
 54            current_position = segment_end
 55
 56        return total_strength, has_paint
 57
 58    def __mul__(self, other):
 59        if self.top_cracked or other.top_cracked:
 60            raise TypeError("Cannot clash with cracked top side")
 61
 62        my_strength, my_has_paint = self._strength("top")
 63        other_strength, other_has_paint = other._strength("top")
 64
 65        if my_strength > other_strength:
 66            winner = self
 67            loser = other
 68        elif other_strength > my_strength:
 69            winner = other
 70            loser = self
 71        else:
 72            if my_has_paint and not other_has_paint:
 73                winner = self
 74                loser = other
 75            else:
 76                winner = other
 77                loser = self
 78
 79        loser.top_cracked = True
 80
 81        if self.tournament is not None and self.tournament is other.tournament:
 82            self.tournament.record_match(self, other, "top", winner)
 83
 84        return winner
 85
 86    def __matmul__(self, other):
 87        if self.bottom_cracked or other.bottom_cracked:
 88            raise TypeError("Cannot clash with cracked bottom side")
 89
 90        my_strength, my_has_paint = self._strength("bottom")
 91        other_strength, other_has_paint = other._strength("bottom")
 92
 93        if my_strength > other_strength:
 94            winner = self
 95            loser = other
 96        elif other_strength > my_strength:
 97            winner = other
 98            loser = self
 99        else:
100            if my_has_paint and not other_has_paint:
101                winner = self
102                loser = other
103            else:
104                winner = other
105                loser = self
106
107        loser.bottom_cracked = True
108
109        if self.tournament is not None and self.tournament is other.tournament:
110            self.tournament.record_match(self, other, "bottom", winner)
111
112        return winner
113
114
115class EggTournament:
116    def __init__(self):
117        self.eggs_by_name = {}
118        self.names_by_egg = {}
119        self.wins = {}
120        self.matches = {}
121
122    def register(self, egg, name):
123        if not isinstance(egg, Egg):
124            raise TypeError("Invalid egg")
125
126        if egg.tournament is not None:
127            raise ValueError("An egg cannot be registered in multiple tournaments")
128
129        if not isinstance(name, str) or not name.isidentifier() or keyword.iskeyword(name):
130            raise ValueError("Invalid registration name")
131
132        if name in self.eggs_by_name:
133            raise ValueError(f"Egg with name {name} has already been registered")
134
135        self.eggs_by_name[name] = egg
136        self.names_by_egg[egg] = name
137        self.wins[egg] = 0
138        egg.tournament = self
139
140    def record_match(self, egg1, egg2, side, winner):
141        key = (frozenset({egg1, egg2}), side)
142        self.matches[key] = winner
143        self.wins[winner] += 1
144
145    def __getitem__(self, item):
146        if isinstance(item, tuple):
147            if len(item) != 3:
148                raise KeyError
149            egg1, egg2, side = item
150        elif isinstance(item, slice):
151            egg1 = item.start
152            egg2 = item.stop
153            side = item.step
154        else:
155            raise KeyError
156
157        key = (frozenset({egg1, egg2}), side)
158
159        if key not in self.matches:
160            raise KeyError
161
162        return self.matches[key]
163
164    def _ranking(self):
165        grouped_by_wins = {}
166
167        for egg, victories in self.wins.items():
168            if victories not in grouped_by_wins:
169                grouped_by_wins[victories] = set()
170
171            grouped_by_wins[victories].add(egg)
172
173        sorted_victories = sorted(grouped_by_wins.keys(), reverse=True)
174        ranking = {}
175        position = 1
176
177        for victory in sorted_victories:
178            ranking[position] = grouped_by_wins[victory]
179            position += 1
180
181        return ranking
182
183    def __rmatmul__(self, position):
184        ranking = self._ranking()
185
186        if position not in ranking:
187            raise IndexError
188
189        eggs_on_position = ranking[position]
190
191        if len(eggs_on_position) == 1:
192            return next(iter(eggs_on_position))
193
194        return eggs_on_position
195
196    def _ranking_of_egg(self, egg):
197        ranking = self._ranking()
198
199        for position, eggs in ranking.items():
200            if egg in eggs:
201                return position
202
203
204    def __getattr__(self, name):
205        if name not in self.eggs_by_name:
206            raise AttributeError("Apologies, there is no such egg registered")
207
208        egg = self.eggs_by_name[name]
209
210        return {"position": self._ranking_of_egg(egg),
211                "victories": self.wins[egg]}
212
213    def __contains__(self, egg):
214        return egg in self.names_by_egg

..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.001s

OK

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