1class Egg:
2 def __init__(self):
3 self.percentage_painted = 0
4 self.colors = []
5 self.upper_broken = False
6 self.lower_broken = False
7
8 def paint(self, *pairs):
9 added_percentage = sum(percentage for hex_color, percentage in pairs)
10 if self.percentage_painted + added_percentage > 100:
11 raise ValueError("Cannot paint the egg more than 100%!")
12 for hex_color, percentage in pairs:
13 self.colors.append((hex_color.lower(), percentage))
14 self.percentage_painted += added_percentage
15
16 def color_durability(self, hex_color):
17 r = int(hex_color[0:2], 16)
18 g = int(hex_color[2:4], 16)
19 b = int(hex_color[4:6], 16)
20 return r + g + b
21
22 @property
23 def _upper_durability(self):
24 if self.percentage_painted == 0:
25 return -1
26 current_procentage = 0
27 durability = 0
28 for hex_color, percentage in self.colors:
29 if current_procentage + percentage > 50:
30 durability += (50 - current_procentage) * self.color_durability(hex_color)
31 return durability
32 durability += percentage * self.color_durability(hex_color)
33 current_procentage += percentage
34 return durability
35
36 @property
37 def _lower_durability(self):
38 if self.percentage_painted <= 50:
39 return -1
40 current_procentage = 0
41 durability = 0
42 max_procentage = self.percentage_painted - 50
43 for hex_color, percentage in self.colors[::-1]:
44 if current_procentage + percentage > max_procentage:
45 durability += (max_procentage - current_procentage) * self.color_durability(hex_color)
46 return durability
47 durability += percentage * self.color_durability(hex_color)
48 current_procentage += percentage
49 return durability
50
51 def __mul__(self, other):
52 if self.upper_broken:
53 raise TypeError("This egg's upper side is already broken!")
54 if other.upper_broken:
55 raise TypeError("The other egg's upper side is already broken!")
56 winner = self if self._upper_durability >= other._upper_durability else other
57 loser = other if winner is self else self
58 loser.upper_broken = True
59 if hasattr(self, 'tournament'):
60 self.tournament.record(self, other, "top", winner)
61 return winner
62
63 def __matmul__(self, other):
64 if self.lower_broken:
65 raise TypeError("This egg's lower side is already broken!")
66 if other.lower_broken:
67 raise TypeError("The other egg's lower side is already broken!")
68 winner = self if self._lower_durability >= other._lower_durability else other
69 loser = other if winner is self else self
70 loser.lower_broken = True
71 if hasattr(self, 'tournament'):
72 self.tournament.record(self, other, "bottom", winner)
73 return winner
74
75
76class EggTournament:
77 def __init__(self):
78 self.eggs = {}
79 self.history = []
80
81 def register(self, egg, name):
82 if not name.isidentifier():
83 raise ValueError("Invalid registration name")
84 if hasattr(egg, 'tournament'):
85 raise ValueError("An egg cannot be registered in multiple tournaments")
86 if name in self.eggs:
87 raise ValueError(f"Egg with name {name} has already been registered")
88 egg.tournament = self
89 self.eggs[name] = egg
90
91 def record(self, egg1, egg2, side, winner):
92 registered = set(self.eggs.values())
93 if egg1 in registered and egg2 in registered:
94 self.history.append((egg1, egg2, side, winner))
95
96 def __getitem__(self, key):
97 if isinstance(key, tuple):
98 egg1, egg2, side = key
99 elif isinstance(key, slice):
100 egg1, egg2, side = key.start, key.stop, key.step
101 else:
102 raise KeyError(key)
103 for h_egg1, h_egg2, h_side, winner in self.history:
104 if h_side == side and {h_egg1, h_egg2} == {egg1, egg2}:
105 return winner
106 raise KeyError(f"No match found between the two eggs on side '{side}'")
107
108 def _get_wins(self): # Това исках да го направя с @property ама ми ставаха някакви безкрайни рекурсии от getattr
109 wins = {e: 0 for e in self.eggs.values()}
110 for h_egg1, h_egg2, h_side, winner in self.history:
111 if winner in wins:
112 wins[winner] += 1
113 return wins
114
115 def __rmatmul__(self, position):
116 wins = self._get_wins()
117 sorted_wins = sorted(set(wins.values()), reverse=True)
118 if position > len(sorted_wins):
119 raise IndexError(f"No egg at position {position}")
120 target_wins = sorted_wins[position - 1]
121 result = {egg for egg, win_count in wins.items() if win_count == target_wins}
122 if len(result) == 1:
123 return next(iter(result))
124 return result
125
126 def __getattr__(self, name):
127 if name not in self.eggs:
128 raise AttributeError("Apologies, there is no such egg registered")
129 egg = self.eggs[name]
130 wins = self._get_wins()
131 egg_wins = wins[egg]
132 sorted_wins = sorted(set(wins.values()), reverse=True)
133 position = sorted_wins.index(egg_wins) + 1
134 return {"position": position, "victories": egg_wins}
135
136 def __contains__(self, egg):
137 return egg in self.eggs.values()
..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.001s
OK
Виктор Бечев
15.04.2026 16:58Като цяло - добре решение. Добрата структура на данните и property-тата ти прави живота лесен. Въпреки повторението на кода в `__mul__` и `__matmul__` ми се иска да те поощря.
И тъй като няма да дойде ФМИ полицията - ще го направя. Печелиш бонус точка.
|
15.04.2026 16:53
15.04.2026 16:56
15.04.2026 16:58