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Браво, чисто решение, с дребни проблеми.
|
15.04.2026 13:54