1class Egg:
2 def __init__(self):
3 self._painted = 0.0
4 self._segments = []
5 self._broken_top = False
6 self._broken_bottom = False
7 self._tournament = None
8
9 def paint(self, *args):
10 total = 0
11 for _, percentage in args:
12 total += percentage
13 if self._painted + total > 100.0:
14 raise ValueError("Egg overpainted")
15 current = self._painted
16 for hex_color, percentage in args:
17 pigment = self._pigment_value(hex_color)
18 start = current
19 end = current + percentage
20 self._segments.append((start, end, pigment))
21 current = end
22 self._painted = current
23
24 def __mul__(self, other):
25 return self._battle(other, "top")
26
27 def __matmul__(self, other):
28 return self._battle(other, "bottom")
29
30 def _battle(self, other, side):
31 if side == "top":
32 if self._broken_top or other._broken_top:
33 raise TypeError("Broken side cannot be used again")
34 else:
35 if self._broken_bottom or other._broken_bottom:
36 raise TypeError("Broken side cannot be used again")
37 my_strength = self._side_strength(side)
38 other_strength = other._side_strength(side)
39 if my_strength > other_strength:
40 winner = self
41 loser = other
42 else:
43 winner = other
44 loser = self
45 if side == "top":
46 loser._broken_top = True
47 else:
48 loser._broken_bottom = True
49 if self._tournament is not None:
50 if self._tournament is other._tournament:
51 if self in self._tournament and other in self._tournament:
52 self._tournament._record_battle(self, other, side, winner)
53 return winner
54
55 def _side_strength(self, side):
56 if side == "top":
57 start, end = 0.0, 50.0
58 else:
59 start, end = 50.0, 100.0
60 pigment_sum = 0.0
61 coverage = 0.0
62 for seg_start, seg_end, pigment in self._segments:
63 overlap_start = max(start, seg_start)
64 overlap_end = min(end, seg_end)
65 if overlap_start < overlap_end:
66 overlap = overlap_end - overlap_start
67 pigment_sum += overlap * pigment
68 coverage += overlap
69 return pigment_sum, coverage
70
71 @staticmethod
72 def _pigment_value(hex_color):
73 hex_color = hex_color.upper()
74 r = int(hex_color[0:2], 16)
75 g = int(hex_color[2:4], 16)
76 b = int(hex_color[4:6], 16)
77 return r + g + b
78
79
80class EggTournament:
81 def __init__(self):
82 self._eggs_by_name = {}
83 self._names_by_egg = {}
84 self._victories = {}
85 self._history = {}
86
87 def register(self, egg, name):
88 if not name.isidentifier():
89 raise ValueError("Invalid registration name")
90 if egg._tournament is not None:
91 if egg._tournament is not self:
92 raise ValueError("An egg cannot be registered in multiple tournaments")
93 if egg in self._names_by_egg:
94 raise ValueError("An egg cannot be registered in multiple tournaments")
95 if name in self._eggs_by_name:
96 raise ValueError(f"Egg with name {name} has already been registered")
97 self._eggs_by_name[name] = egg
98 self._names_by_egg[egg] = name
99 self._victories[egg] = 0
100 egg._tournament = self
101
102 def _record_battle(self, egg1, egg2, side, winner):
103 key = (frozenset((egg1, egg2)), side)
104 self._history[key] = winner
105 if winner in self._victories:
106 self._victories[winner] += 1
107
108 def __getitem__(self, key):
109 if isinstance(key, slice):
110 egg1, egg2, side = key.start, key.stop, key.step
111 else:
112 egg1, egg2, side = key[0], key[1], key[2]
113 history_key = (frozenset((egg1, egg2)), side)
114 if history_key not in self._history:
115 raise KeyError("No such battle found")
116 return self._history[history_key]
117
118 def __rmatmul__(self, position):
119 ranking = self._ranking()
120 if position not in ranking:
121 raise IndexError("No eggs at this position")
122 eggs = ranking[position]
123 if len(eggs) == 1:
124 for egg in eggs:
125 return egg
126 return eggs
127
128 def __getattr__(self, name):
129 if name in self._eggs_by_name:
130 egg = self._eggs_by_name[name]
131 victories = self._victories[egg]
132 position = self._position_of(egg)
133 return {"position": position, "victories": victories}
134 raise AttributeError("Apologies, there is no such egg registered")
135
136 def __contains__(self, egg):
137 return egg in self._names_by_egg
138
139 def _ranking(self):
140 by_wins = {}
141 for egg, wins in self._victories.items():
142 if wins not in by_wins:
143 by_wins[wins] = set()
144 by_wins[wins].add(egg)
145 sorted_wins = sorted(by_wins.keys(), reverse=True)
146 ranking = {}
147 position = 1
148 for wins in sorted_wins:
149 ranking[position] = by_wins[wins]
150 position += 1
151 return ranking
152
153 def _position_of(self, target_egg):
154 ranking = self._ranking()
155 for position, eggs in ranking.items():
156 if target_egg in eggs:
157 return position
..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.001s
OK
16.04.2026 19:02
16.04.2026 19:04
16.04.2026 19:05
16.04.2026 19:09
16.04.2026 19:08
16.04.2026 19:06
16.04.2026 19:12
16.04.2026 19:13
16.04.2026 19:16