1class Egg:
2 def __init__(self):
3 self.painted_part = 0.0
4 self.top_strength = 0.0
5 self.bottom_strength = 0.0
6 self.top_cracked = False
7 self.bottom_cracked = False
8 self.paint_jobs = []
9 self.tournament = None
10
11 def paint(self, *args):
12 total_percent_to_add = sum(p[1] for p in args)
13 if self.painted_part + total_percent_to_add > 100.0:
14 raise ValueError("Cannot overpaint the egg!")
15 for p in args:
16 color = p[0].upper()
17 percent = p[1]
18 red = int(color[:2], 16)
19 green = int(color[2:4], 16)
20 blue = int(color[4:], 16)
21 paint_strength = red + green + blue
22
23 if self.painted_part < 50.0:
24 top_part = min(percent, 50.0 - self.painted_part)
25 self.top_strength += top_part * paint_strength
26 bottom_part = percent - top_part
27 if bottom_part > 0:
28 self.bottom_strength += bottom_part * paint_strength
29 else:
30 self.bottom_strength += percent * paint_strength
31
32 self.painted_part += percent
33 self.paint_jobs.append((color, percent))
34
35 def __mul__(self, other):
36 if self.top_cracked or other.top_cracked:
37 raise TypeError("Cannot battle with a cracked top!")
38
39 if self.top_strength > other.top_strength or (self.top_strength == other.top_strength and self.painted_part > other.painted_part):
40 winner, loser = self, other
41 else:
42 winner, loser = other, self
43
44 loser.top_cracked = True
45
46 if self.tournament and other.tournament:
47 self.tournament._record_battle(self, other, "top", winner)
48
49 return winner
50
51 def __matmul__(self, other):
52 if self.bottom_cracked or other.bottom_cracked:
53 raise TypeError("Cannot battle with a cracked bottom!")
54
55 if self.bottom_strength > other.bottom_strength or (self.bottom_strength == other.bottom_strength and self.painted_part > other.painted_part):
56 winner, loser = self, other
57 else:
58 winner, loser = other, self
59
60 loser.bottom_cracked = True
61
62 if self.tournament and other.tournament:
63 self.tournament._record_battle(self, other, "bottom", winner)
64
65 return winner
66
67
68class EggTournament:
69 def __init__(self):
70 self.eggs = {}
71 self.victories = {}
72 self.history = {}
73
74 def register(self, egg, name):
75 if type(name) is not str or not name.isidentifier():
76 raise ValueError("Invalid registration name")
77 if name in self.eggs:
78 raise ValueError(f"Egg with name {name} has already been registered")
79 if egg.tournament is not None:
80 raise ValueError("An egg cannot be registered in multiple tournaments")
81
82 self.eggs[name] = egg
83 self.victories[egg] = 0
84 egg.tournament = self
85
86 def _record_battle(self, egg1, egg2, side, winner):
87 key = (frozenset({egg1, egg2}), side)
88 self.history[key] = winner
89 self.victories[winner] += 1
90
91 def __getitem__(self, item):
92 if isinstance(item, tuple):
93 egg1, egg2, side = item
94 elif isinstance(item, slice):
95 egg1, egg2, side = item.start, item.stop, item.step
96 else:
97 raise KeyError()
98
99 key = (frozenset({egg1, egg2}), side)
100 if key not in self.history:
101 raise KeyError()
102 return self.history[key]
103
104 def __rmatmul__(self, place):
105 sorted_wins = sorted(set(self.victories.values()), reverse=True)
106 if place < 1 or place > len(sorted_wins):
107 raise IndexError()
108 target_wins = sorted_wins[place - 1]
109 eggs_at_place = {egg for egg, wins in self.victories.items() if wins == target_wins}
110 return list(eggs_at_place)[0] if len(eggs_at_place) == 1 else eggs_at_place
111
112 def __getattr__(self, name):
113 if name not in self.eggs:
114 raise AttributeError("Apologies, there is no such egg registered")
115
116 egg = self.eggs[name]
117 wins = self.victories[egg]
118 sorted_wins = sorted(set(self.victories.values()), reverse=True)
119 position = sorted_wins.index(wins) + 1
120 return {"position": position, "victories": wins}
121
122 def __contains__(self, egg):
123 return egg in self.victories
..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.001s
OK
15.04.2026 16:38
15.04.2026 16:39
15.04.2026 16:40
15.04.2026 16:41