1class Egg:
2 def __init__(self):
3 self._percentage = 0
4 self.top_pigment = None
5 self.bot_pigment = None
6 self.top_broken = False
7 self.bot_broken = False
8 self._tournament = None
9
10 def __mul__(self, other):
11 if self.top_broken or other.top_broken:
12 raise TypeError
13
14 winner = self
15 if self.top_pigment == None:
16 self.top_broken = True
17 winner = other
18 elif other.top_pigment == None:
19 other.top_broken = True
20 winner = self
21 elif self.top_pigment > other.top_pigment:
22 other.top_broken = True
23 winner = self
24 else:
25 self.top_broken = True
26 winner = other
27
28 if self._tournament and other._tournament and self._tournament == other._tournament:
29 self._tournament.wins[winner] += 1
30 self._tournament.fight_history["top"][(self, other)] = winner
31
32 return winner
33
34
35 def __matmul__(self, other):
36 if self.bot_broken or other.bot_broken:
37 raise TypeError
38
39 winner = self
40 if self.bot_pigment == None:
41 self.bot_broken = True
42 winner = other
43 elif other.bot_pigment == None:
44 other.bot_broken = True
45 winner = self
46 elif self.bot_pigment > other.bot_pigment:
47 other.bot_broken = True
48 winner = self
49 else:
50 self.bot_broken = True
51 winner = other
52
53 if self._tournament and other._tournament and self._tournament == other._tournament:
54 self._tournament.wins[winner] += 1
55 self._tournament.fight_history["bottom"][(self, other)] = winner
56
57 return winner
58
59 def paint(self, *colors):
60 total_percentage = self._percentage
61 for _, percentage in colors:
62 total_percentage += percentage
63 if total_percentage > 100:
64 raise ValueError
65
66 for color, percentage in colors:
67 pigment = int(color[:2], 16) + int(color[2:4], 16) + int(color[4:], 16)
68
69 if self._percentage < 50:
70 left = 50 - self._percentage
71 if percentage <= left:
72 self._percentage += percentage
73
74 # TOP
75 if self.top_pigment == None:
76 self.top_pigment = pigment * 2 * percentage / 100
77 else:
78 self.top_pigment += pigment * 2 * percentage / 100
79 else:
80 self._percentage += percentage
81
82 #TOP
83 if self.top_pigment == None:
84 self.top_pigment = pigment * 2 * left / 100
85 else:
86 self.top_pigment += pigment * 2 * left / 100
87
88 #BOT
89 if self.bot_pigment == None:
90 self.bot_pigment = pigment * (percentage - left) / 100 * 2
91 else:
92 self.bot_pigment += pigment * (percentage - left) / 100 * 2
93 else:
94 self._percentage += percentage
95
96 #BOT
97 if self.bot_pigment == None:
98 self.bot_pigment = pigment * percentage / 100 * 2
99 else:
100 self.bot_pigment += pigment * percentage / 100 * 2
101
102
103class EggTournament:
104 all_registered_eggs = set()
105
106 def __init__(self):
107 self.eggs = {} #nick : egg, wins
108 self.egg_nick = {} #egg : nick
109 self.fight_history = {"top": {}, "bottom": {}} #(egg1, egg2) = winner
110 self.wins = {} #egg: wins
111
112 def register(self, egg, nick):
113 if not nick.isidentifier():
114 raise ValueError("Invalid registration name")
115
116 if nick in self.eggs:
117 raise ValueError(f"Egg with name {nick} has already been registered")
118
119 if egg in EggTournament.all_registered_eggs:
120 raise ValueError("An egg cannot be registered in multiple tournaments")
121
122 self.eggs[nick] = egg
123 self.egg_nick[egg] = nick
124 egg._tournament = self
125 self.wins[egg] = 0
126 EggTournament.all_registered_eggs.add(egg)
127
128 def __getitem__(self, key):
129 if isinstance(key, slice):
130 egg1 = key.start
131 egg2 = key.stop
132 pos = key.step
133 elif isinstance(key, tuple):
134 egg1, egg2, pos = key
135
136 fights = self.fight_history[pos]
137 try:
138 return fights[(egg1, egg2)]
139 except KeyError:
140 return fights[(egg2, egg1)]
141
142 def ranking(self):
143 result = {}
144 sorted_wins = sorted(self.wins.items(), key = lambda x : x[1], reverse=True)
145
146 rank = 1
147 last = -1
148 for egg, wins in sorted_wins:
149 if last == -1:
150 last = wins
151 result[rank] = {egg}
152 elif last == wins:
153 result[rank].add(egg)
154 elif last != wins:
155 rank += 1
156 result[rank] = {egg}
157 last = wins
158
159 return result
160
161
162 def __rmatmul__(self, pos):
163 ranking = self.ranking()
164
165 if not pos in ranking:
166 raise IndexError
167
168 return ranking[pos]
169
170 def __getattr__(self, name):
171 if not name in self.eggs:
172 raise AttributeError("Apologies, there is no such egg registered")
173
174 egg = self.eggs[name]
175
176 wins = self.wins.get(egg, 0)
177 ranking = self.ranking()
178 position = -1
179 for pos, eggs in ranking.items():
180 if egg in eggs:
181 position = pos
182 break
183
184 return {"position": position, "victories": wins}
185
186 def __contains__(self, egg):
187 return egg in self.egg_nick
........................F...............FF....
======================================================================
FAIL: test_collision_between_two_registered_eggs_is_recorded (test.TestEggTournament.test_collision_between_two_registered_eggs_is_recorded)
A collision between two registered eggs should be recorded in the tournament.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 373, in test_collision_between_two_registered_eggs_is_recorded
self.assertIs(1 @ tournament, first_egg)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: {<solution.Egg object at 0x7aa0faf51d50>} is not <solution.Egg object at 0x7aa0faf51d50>
======================================================================
FAIL: test_ranking_unique_position_returns_single_egg (test.TestEggTournament.test_ranking_unique_position_returns_single_egg)
Looking up a unique ranking position should return a single egg.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 478, in test_ranking_unique_position_returns_single_egg
self.assertIs(1 @ tournament, alpha)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: {<solution.Egg object at 0x7aa0fad2ce50>} is not <solution.Egg object at 0x7aa0fad2ce50>
======================================================================
FAIL: test_ranking_uses_dense_ranking_without_skipping_places (test.TestEggTournament.test_ranking_uses_dense_ranking_without_skipping_places)
Looking up ranking positions should use dense ranking without skipping places.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 514, in test_ranking_uses_dense_ranking_without_skipping_places
self.assertIs(1 @ tournament, alpha)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: {<solution.Egg object at 0x7aa0fad2cf50>} is not <solution.Egg object at 0x7aa0fad2cf50>
----------------------------------------------------------------------
Ran 46 tests in 0.002s
FAILED (failures=3)
16.04.2026 18:23
16.04.2026 18:25
16.04.2026 18:26
16.04.2026 18:29
16.04.2026 18:31