1EPS = 1e-9
2
3class Egg:
4 def __init__(self):
5 self.colors = []
6 self.top_broken = False
7 self.bottom_broken = False
8 self.tournament = None
9
10 def paint(self, *args):
11 if sum(percentage for color, percentage in self.colors) + sum(percentage for color, percentage in args) > 100 + EPS:
12 raise ValueError("Paint is more than 100%")
13 for hex_color, percentage in args:
14 self.colors.append((hex_color.upper(), percentage))
15
16 def _count_strength(self, start, end):
17 total = 0.0
18 filled = 0.0
19 has_paint = False
20 for hex_color, percentage in self.colors:
21 segment_start = filled
22 segment_end = filled + percentage
23 part_percentage = max(0, min(segment_end, end) - max(segment_start, start))
24 if part_percentage > 0:
25 has_paint = True
26 total += (int(hex_color[:2], 16) + int(hex_color[2:4], 16) + int(hex_color[4:], 16)) * (part_percentage / 50)
27 filled = segment_end
28 return total, has_paint
29
30 def _top_strength(self):
31 return self._count_strength(0, 50)
32
33 def _bottom_strength(self):
34 return self._count_strength(50, 100)
35
36 def __mul__(self, other):
37 if self.top_broken or other.top_broken:
38 raise TypeError("Top side already broken")
39 my_strength, my_painted = self._top_strength()
40 other_strength, other_painted = other._top_strength()
41 if not my_painted and other_painted:
42 self.top_broken = True
43 winner = other
44 elif not other_painted and my_painted:
45 other.top_broken = True
46 winner = self
47 elif my_strength > other_strength:
48 other.top_broken = True
49 winner = self
50 else:
51 self.top_broken = True
52 winner = other
53 if self.tournament and self.tournament is other.tournament:
54 self.tournament.record_battle(self, other, "top", winner)
55 return winner
56
57 def __matmul__(self, other):
58 if self.bottom_broken or other.bottom_broken:
59 raise TypeError("Bottom side already broken")
60 my_strength, my_painted = self._bottom_strength()
61 other_strength, other_painted = other._bottom_strength()
62 if not my_painted and other_painted:
63 self.bottom_broken = True
64 winner = other
65 elif not other_painted and my_painted:
66 other.bottom_broken = True
67 winner = self
68 elif my_strength > other_strength:
69 other.bottom_broken = True
70 winner = self
71 else:
72 self.bottom_broken = True
73 winner = other
74 if self.tournament and self.tournament is other.tournament:
75 self.tournament.record_battle(self, other, "bottom", winner)
76 return winner
77
78
79class EggTournament:
80 def __init__(self):
81 self._eggs = {}
82 self._wins = {}
83 self._history = {}
84
85 def register(self, egg, name):
86 if egg.tournament is not None:
87 raise ValueError("An egg cannot be registered in multiple tournaments")
88 if not name.isidentifier():
89 raise ValueError("Invalid registration name")
90 if name in self._eggs:
91 raise ValueError(f"Egg with name {name} has already been registered")
92 self._eggs[name] = egg
93 self._wins[egg] = 0
94 egg.tournament = self
95
96 def record_battle(self, egg1, egg2, side, winner):
97 if egg1 not in self or egg2 not in self:
98 return
99 self._history[(frozenset((egg1, egg2)), side)] = winner
100 self._wins[winner] += 1
101
102 def __getitem__(self, key):
103 if isinstance(key, tuple):
104 egg1, egg2, side = key
105 elif isinstance(key, slice):
106 egg1, egg2, side = key.start, key.stop, key.step
107 else:
108 raise KeyError
109 pair = frozenset((egg1, egg2))
110 if (pair, side) not in self._history:
111 raise KeyError("No match found")
112 return self._history[(pair, side)]
113
114 def _ranking(self):
115 sorted_eggs = sorted(self._wins.items(), key=lambda pair: pair[1], reverse=True)
116 ranking = {}
117 current_position = 1
118 previous_wins = None
119 for egg, wins in sorted_eggs:
120 if previous_wins is None:
121 ranking[egg] = current_position
122 elif wins < previous_wins:
123 current_position += 1
124 ranking[egg] = current_position
125 else:
126 ranking[egg] = current_position
127 previous_wins = wins
128 return ranking
129
130 def __rmatmul__(self, position):
131 ranking = self._ranking()
132 result = {egg for egg, pos in ranking.items() if pos == position}
133 if not result:
134 raise IndexError("No such rank")
135 if len(result) == 1:
136 return next(iter(result))
137 return result
138
139 def __getattr__(self, name):
140 if name not in self._eggs:
141 raise AttributeError("Apologies, there is no such egg registered")
142 egg = self._eggs[name]
143 ranking = self._ranking()
144 return {"position": ranking[egg], "victories": self._wins[egg]}
145
146 def __contains__(self, egg):
147 return egg in self._eggs.values()
148
..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.001s
OK
16.04.2026 19:33
16.04.2026 19:33
16.04.2026 19:34
16.04.2026 19:36
16.04.2026 19:36
16.04.2026 19:36