1class Egg:
2 def __init__(self):
3 self.paint_layers = []
4 self.total = 0.0
5 self.broken_top = False
6 self.broken_bottom = False
7 self.tournament = None
8
9 def _color_value(self, hex_color):
10 hex_color = hex_color.upper()
11 r = int(hex_color[0:2], 16)
12 g = int(hex_color[2:4], 16)
13 b = int(hex_color[4:6], 16)
14 return r + g + b
15
16 def paint(self, *args):
17 total_new = sum(p for c, p in args)
18
19 if self.total + total_new > 100:
20 raise ValueError("Overpaint")
21
22 for color, perc in args:
23 val = self._color_value(color)
24 self.paint_layers.append((val, perc))
25 self.total += perc
26
27 def _half_strength(self, half):
28 limit = 50.0
29 current = 0.0
30 strength = 0.0
31
32 for val, perc in self.paint_layers:
33 if half == "top":
34 if current >= 50:
35 break
36 usable = min(perc, 50 - current)
37 strength += val * (usable / 100)
38 current += perc
39 else:
40 if current + perc <= 50:
41 current += perc
42 continue
43 overlap_start = max(current, 50)
44 overlap = min(current + perc, 100) - overlap_start
45 if overlap > 0:
46 strength += val * (overlap / 100)
47 current += perc
48
49 return strength
50
51 def _fight(self, other, side):
52 if side == "top":
53 if self.broken_top or other.broken_top:
54 raise TypeError("Broken egg")
55 else:
56 if self.broken_bottom or other.broken_bottom:
57 raise TypeError("Broken egg")
58
59 s1 = self._half_strength(side)
60 s2 = other._half_strength(side)
61
62 winner = self if s1 > s2 else other
63 loser = other if winner is self else self
64
65 if side == "top":
66 loser.broken_top = True
67 else:
68 loser.broken_bottom = True
69 if self.tournament and self.tournament is other.tournament:
70 self.tournament._record(self, other, side, winner)
71
72 return winner
73
74 def __mul__(self, other):
75 #*
76 return self._fight(other, "top")
77
78 def __matmul__(self, other):
79 #@
80 return self._fight(other, "bottom")
81
82
83class EggTournament:
84 def __init__(self):
85 self.eggs = {}
86 self.reverse = {}
87 self.history = {}
88 self.wins = {}
89
90 def register(self, egg, name):
91 if not name.isidentifier():
92 raise ValueError("Invalid registration name")
93 if egg.tournament:
94 raise ValueError("An egg cannot be registered in more than one tournament")
95 if name in self.eggs:
96 raise ValueError(f"Egg with name {name} has already been registered")
97 self.eggs[name] = egg
98 self.reverse[egg] = name
99 self.wins[egg] = 0
100 egg.tournament = self
101
102 def _record(self, e1, e2, side, winner):
103 key = (frozenset([e1, e2]), side)
104 #I saw that it would be better than just "set" in this case
105 self.history[key] = winner
106 self.wins[winner] += 1
107
108 def __getitem__(self, key):
109 if isinstance(key, tuple):
110 e1, e2, side = key
111 else:
112 e1, e2, side = key.start, key.stop, key.step
113 #I searched extra for reading with ':' as a separator
114 k = (frozenset([e1, e2]), side)
115 if k not in self.history:
116 raise KeyError
117
118 return self.history[k]
119
120 def __rmatmul__(self, pos):
121 sorted_eggs = sorted(self.wins.items(), key=lambda x: -x[1])
122
123 result = {}
124 rank = 1
125 prev = None
126 group = []
127
128 for egg, w in sorted_eggs:
129 if prev is None or w == prev:
130 group.append(egg)
131 else:
132 result[rank] = set(group)
133 rank += 1
134 group = [egg]
135 prev = w
136
137 if group:
138 result[rank] = set(group)
139 if pos not in result:
140 raise IndexError
141
142 return result[pos]
143
144 def __getattr__(self, name):
145 if name not in self.eggs:
146 raise AttributeError("There is no such egg registered")
147 egg = self.eggs[name]
148 wins = self.wins[egg]
149
150 sorted_eggs = sorted(self.wins.items(), key=lambda x: -x[1])
151 rank = 1
152 prev = None
153
154 for i, (e, w) in enumerate(sorted_eggs):
155 if prev is not None and w < prev:
156 rank += 1
157 if e == egg:
158 return {"position": rank, "victories": wins}
159 prev = w
160
161 def __contains__(self, egg):
162 return egg in self.reverse
.....................F..F....F.......F..FF....
======================================================================
FAIL: test_unpainted_half_loses_to_half_painted_black (test.TestEgg.test_unpainted_half_loses_to_half_painted_black)
An unpainted half should lose to a half painted in black.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 205, in test_unpainted_half_loses_to_half_painted_black
self.assertIs(black_egg * unpainted_egg, black_egg)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: <solution.Egg object at 0x7e086bb8cde0> is not <solution.Egg object at 0x7e086bb8cc90>
======================================================================
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 0x7e086bb8cd70>} is not <solution.Egg object at 0x7e086bb8cd70>
======================================================================
FAIL: test_egg_cannot_be_registered_in_second_tournament (test.TestEggTournament.test_egg_cannot_be_registered_in_second_tournament)
Registering an egg in a second tournament should raise a ValueError.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 344, in test_egg_cannot_be_registered_in_second_tournament
self.assertEqual(
~~~~~~~~~~~~~~~~^
str(context.exception),
^^^^^^^^^^^^^^^^^^^^^^^
"An egg cannot be registered in multiple tournaments",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
AssertionError: 'An egg cannot be registered in more than one tournament' != 'An egg cannot be registered in multiple tournaments'
- An egg cannot be registered in more than one tournament
? ^^ ---------
+ An egg cannot be registered in multiple tournaments
? ^^^^^^ +
======================================================================
FAIL: test_missing_egg_attribute_raises_attribute_error (test.TestEggTournament.test_missing_egg_attribute_raises_attribute_error)
Accessing an unregistered egg as an attribute should raise an AttributeError.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 586, in test_missing_egg_attribute_raises_attribute_error
self.assertEqual(
~~~~~~~~~~~~~~~~^
str(context.exception),
^^^^^^^^^^^^^^^^^^^^^^^
"Apologies, there is no such egg registered",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
AssertionError: 'There is no such egg registered' != 'Apologies, there is no such egg registered'
- There is no such egg registered
? ^
+ Apologies, there is no such egg registered
? ^^^^^^^^^^^^
======================================================================
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 0x7e086b8a11d0>} is not <solution.Egg object at 0x7e086b8a11d0>
======================================================================
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 0x7e086b8a12b0>} is not <solution.Egg object at 0x7e086b8a12b0>
----------------------------------------------------------------------
Ran 46 tests in 0.003s
FAILED (failures=6)
Гергана Панделиева
14.04.2026 23:00Така ми дойде за коментара под домашното. А за гадните имена на променливите така очевидно съм забравила да ги оставя от пишенето и рънването на отделни функции уж само за “тестването”, ама излезе че така съм си ги оставила щом съм видяла, че работи, за друг път ще внимавам 🫡
|
Виктор Бечев
12.04.2026 22:18Отвъд имената на променливите е добре - използвала си правилните питонизми и не си прекалила с `if`-овете и `for`-овете.
И най-важното - предала си го **дни** преди крайния срок.
|
Виктор Бечев
12.04.2026 22:10Интересно място да ни оставиш коментар за това какво да преговорим. 😂
|
12.04.2026 22:10
12.04.2026 22:13
12.04.2026 22:15
12.04.2026 22:16