Домашни > Великденско домашно > Решения > Решението на Цветинка Хаджиева

Резултати
6 точки от тестове
0 точки от учител

6 точки общо

46 успешни теста
0 неуспешни теста
Код
Скрий всички коментари

  1class Egg:
  2    def __init__(self):
  3        self.parts = [] 
  4        self.filled = 0.0
  5
  6        self.top_broken = False
  7        self.bottom_broken = False
  8
  9        self.tournament = None
 10
 11    def paint(self, *args):
 12        total_to_add = 0.0
 13
 14        for color, percent in args:
 15            total_to_add += percent
 16
 17        if self.filled + total_to_add > 100.0:
 18            raise ValueError("Too much paint")
 19
 20        current_start = self.filled
 21        new_parts = []
 22
 23        for color, percent in args:
 24            pigment = self._get_pigment(color)
 25            current_end = current_start + percent
 26            new_parts.append((current_start, current_end, pigment))
 27            current_start = current_end
 28
 29        self.parts.extend(new_parts)
 30        self.filled += total_to_add
 31
 32    def _get_pigment(self, hex_color):
 33        hex_color = hex_color.upper()
 34
 35        r = int(hex_color[0:2], 16)
 36        g = int(hex_color[2:4], 16)
 37        b = int(hex_color[4:6], 16)
 38
 39        return r + g + b
 40
 41    def _get_side_info(self, side):
 42        if side == "top":
 43            side_start = 0.0
 44            side_end = 50.0
 45        elif side == "bottom":
 46            side_start = 50.0
 47            side_end = 100.0
 48        else:
 49            raise ValueError("Invalid side")
 50
 51        total_strength = 0.0
 52        total_coverage = 0.0
 53
 54        for start, end, pigment in self.parts:
 55            overlap_start = max(start, side_start)
 56            overlap_end = min(end, side_end)
 57
 58            if overlap_start < overlap_end:
 59                overlap_length = overlap_end - overlap_start
 60                total_coverage += overlap_length
 61                total_strength += pigment * (overlap_length / 50.0)
 62
 63        return total_strength, total_coverage
 64
 65    def _fight(self, other, side):
 66        if not isinstance(other, Egg):
 67            return NotImplemented
 68
 69        if side == "top":
 70            if self.top_broken or other.top_broken:
 71                raise TypeError("One of the eggs has a broken top side")
 72        elif side == "bottom":
 73            if self.bottom_broken or other.bottom_broken:
 74                raise TypeError("One of the eggs has a broken bottom side")
 75        else:
 76            raise ValueError("Invalid side")
 77
 78        my_strength, my_coverage = self._get_side_info(side)
 79        other_strength, other_coverage = other._get_side_info(side)
 80
 81        if my_strength > other_strength:
 82            winner = self
 83            loser = other
 84        elif other_strength > my_strength:
 85            winner = other
 86            loser = self
 87        else:
 88            if my_coverage > other_coverage:
 89                winner = self
 90                loser = other
 91            elif other_coverage > my_coverage:
 92                winner = other
 93                loser = self
 94            else:
 95               
 96                winner = self
 97                loser = other
 98
 99        if side == "top":
100            loser.top_broken = True
101        else:
102            loser.bottom_broken = True
103
104        if self.tournament is not None and self.tournament is other.tournament:
105            self.tournament._record_battle(self, other, side, winner)
106
107        return winner
108
109    def __mul__(self, other):
110        return self._fight(other, "top")
111
112    def __matmul__(self, other):
113        return self._fight(other, "bottom")
114
115
116class EggTournament:
117    def __init__(self):
118        self.name_to_egg = {}
119        self.egg_to_name = {}
120        self.wins = {}
121
122        self.battles = []
123
124    def register(self, egg, name):
125        if egg.tournament is not None:
126            raise ValueError("An egg cannot be registered in multiple tournaments")
127
128        if not name.isidentifier():
129            raise ValueError("Invalid registration name")
130
131        if name in self.name_to_egg:
132            raise ValueError(f"Egg with name {name} has already been registered")
133
134        self.name_to_egg[name] = egg
135        self.egg_to_name[egg] = name
136        self.wins[egg] = 0
137        egg.tournament = self
138
139    def _record_battle(self, egg1, egg2, side, winner):
140        if egg1 not in self.egg_to_name or egg2 not in self.egg_to_name:
141            return
142
143        self.battles.append({
144            "egg1": egg1,
145            "egg2": egg2,
146            "side": side,
147            "winner": winner
148        })
149
150        self.wins[winner] += 1
151
152    def __getitem__(self, key):
153        if isinstance(key, tuple):
154            if len(key) != 3:
155                raise KeyError("Invalid key")
156            egg1, egg2, side = key
157        elif isinstance(key, slice):
158            egg1 = key.start
159            egg2 = key.stop
160            side = key.step
161        else:
162            raise KeyError("Invalid key")
163
164        if side not in ("top", "bottom"):
165            raise KeyError("Invalid key")
166
167        for battle in reversed(self.battles):
168            same_pair = (
169                (battle["egg1"] is egg1 and battle["egg2"] is egg2) or
170                (battle["egg1"] is egg2 and battle["egg2"] is egg1)
171            )
172
173            if same_pair and battle["side"] == side:
174                return battle["winner"]
175
176        raise KeyError("No such battle")
177
178    def _get_positions(self):
179        sorted_eggs = sorted(self.wins.items(), key=lambda pair: pair[1], reverse=True)
180
181        positions = {}
182        current_position = 1
183
184        for i in range(len(sorted_eggs)):
185            egg, wins = sorted_eggs[i]
186
187            if i == 0:
188                positions[egg] = current_position
189            else:
190                previous_egg, previous_wins = sorted_eggs[i - 1]
191
192                if wins < previous_wins:
193                    current_position += 1
194
195                positions[egg] = current_position
196
197        return positions
198
199    def __rmatmul__(self, place):
200        positions = self._get_positions()
201        result = set()
202
203        for egg, position in positions.items():
204            if position == place:
205                result.add(egg)
206
207        if len(result) == 0:
208            raise IndexError("No eggs on this position")
209
210        if len(result) == 1:
211            return next(iter(result))
212
213        return result
214
215    def __getattr__(self, name):
216        if name in self.name_to_egg:
217            egg = self.name_to_egg[name]
218            positions = self._get_positions()
219
220            return {
221                "position": positions[egg],
222                "victories": self.wins[egg]
223            }
224
225        raise AttributeError("Apologies, there is no such egg registered")
226
227    def __contains__(self, egg):
228        return egg in self.egg_to_name

..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.001s

OK

Дискусия
История

f1class Egg:f1class Egg:
2    def __init__(self):2    def __init__(self):
n3        self.parts = []  # (start, end, pigment)n3        self.parts = [] 
4        self.filled = 0.04        self.filled = 0.0
55
6        self.top_broken = False6        self.top_broken = False
7        self.bottom_broken = False7        self.bottom_broken = False
88
9        self.tournament = None9        self.tournament = None
1010
11    def paint(self, *args):11    def paint(self, *args):
12        total_to_add = 0.012        total_to_add = 0.0
1313
14        for color, percent in args:14        for color, percent in args:
15            total_to_add += percent15            total_to_add += percent
1616
17        if self.filled + total_to_add > 100.0:17        if self.filled + total_to_add > 100.0:
18            raise ValueError("Too much paint")18            raise ValueError("Too much paint")
1919
20        current_start = self.filled20        current_start = self.filled
21        new_parts = []21        new_parts = []
2222
23        for color, percent in args:23        for color, percent in args:
24            pigment = self._get_pigment(color)24            pigment = self._get_pigment(color)
25            current_end = current_start + percent25            current_end = current_start + percent
26            new_parts.append((current_start, current_end, pigment))26            new_parts.append((current_start, current_end, pigment))
27            current_start = current_end27            current_start = current_end
2828
29        self.parts.extend(new_parts)29        self.parts.extend(new_parts)
30        self.filled += total_to_add30        self.filled += total_to_add
3131
32    def _get_pigment(self, hex_color):32    def _get_pigment(self, hex_color):
33        hex_color = hex_color.upper()33        hex_color = hex_color.upper()
3434
35        r = int(hex_color[0:2], 16)35        r = int(hex_color[0:2], 16)
36        g = int(hex_color[2:4], 16)36        g = int(hex_color[2:4], 16)
37        b = int(hex_color[4:6], 16)37        b = int(hex_color[4:6], 16)
3838
39        return r + g + b39        return r + g + b
4040
41    def _get_side_info(self, side):41    def _get_side_info(self, side):
42        if side == "top":42        if side == "top":
43            side_start = 0.043            side_start = 0.0
44            side_end = 50.044            side_end = 50.0
45        elif side == "bottom":45        elif side == "bottom":
46            side_start = 50.046            side_start = 50.0
47            side_end = 100.047            side_end = 100.0
48        else:48        else:
49            raise ValueError("Invalid side")49            raise ValueError("Invalid side")
5050
51        total_strength = 0.051        total_strength = 0.0
52        total_coverage = 0.052        total_coverage = 0.0
5353
54        for start, end, pigment in self.parts:54        for start, end, pigment in self.parts:
55            overlap_start = max(start, side_start)55            overlap_start = max(start, side_start)
56            overlap_end = min(end, side_end)56            overlap_end = min(end, side_end)
5757
58            if overlap_start < overlap_end:58            if overlap_start < overlap_end:
59                overlap_length = overlap_end - overlap_start59                overlap_length = overlap_end - overlap_start
60                total_coverage += overlap_length60                total_coverage += overlap_length
61                total_strength += pigment * (overlap_length / 50.0)61                total_strength += pigment * (overlap_length / 50.0)
6262
63        return total_strength, total_coverage63        return total_strength, total_coverage
6464
65    def _fight(self, other, side):65    def _fight(self, other, side):
66        if not isinstance(other, Egg):66        if not isinstance(other, Egg):
67            return NotImplemented67            return NotImplemented
6868
69        if side == "top":69        if side == "top":
70            if self.top_broken or other.top_broken:70            if self.top_broken or other.top_broken:
71                raise TypeError("One of the eggs has a broken top side")71                raise TypeError("One of the eggs has a broken top side")
72        elif side == "bottom":72        elif side == "bottom":
73            if self.bottom_broken or other.bottom_broken:73            if self.bottom_broken or other.bottom_broken:
74                raise TypeError("One of the eggs has a broken bottom side")74                raise TypeError("One of the eggs has a broken bottom side")
75        else:75        else:
76            raise ValueError("Invalid side")76            raise ValueError("Invalid side")
7777
78        my_strength, my_coverage = self._get_side_info(side)78        my_strength, my_coverage = self._get_side_info(side)
79        other_strength, other_coverage = other._get_side_info(side)79        other_strength, other_coverage = other._get_side_info(side)
8080
81        if my_strength > other_strength:81        if my_strength > other_strength:
82            winner = self82            winner = self
83            loser = other83            loser = other
84        elif other_strength > my_strength:84        elif other_strength > my_strength:
85            winner = other85            winner = other
86            loser = self86            loser = self
87        else:87        else:
88            if my_coverage > other_coverage:88            if my_coverage > other_coverage:
89                winner = self89                winner = self
90                loser = other90                loser = other
91            elif other_coverage > my_coverage:91            elif other_coverage > my_coverage:
92                winner = other92                winner = other
93                loser = self93                loser = self
94            else:94            else:
t95                # По условие няма да има равенства, но това е безопасен fallbackt95               
96                winner = self96                winner = self
97                loser = other97                loser = other
9898
99        if side == "top":99        if side == "top":
100            loser.top_broken = True100            loser.top_broken = True
101        else:101        else:
102            loser.bottom_broken = True102            loser.bottom_broken = True
103103
104        if self.tournament is not None and self.tournament is other.tournament:104        if self.tournament is not None and self.tournament is other.tournament:
105            self.tournament._record_battle(self, other, side, winner)105            self.tournament._record_battle(self, other, side, winner)
106106
107        return winner107        return winner
108108
109    def __mul__(self, other):109    def __mul__(self, other):
110        return self._fight(other, "top")110        return self._fight(other, "top")
111111
112    def __matmul__(self, other):112    def __matmul__(self, other):
113        return self._fight(other, "bottom")113        return self._fight(other, "bottom")
114114
115115
116class EggTournament:116class EggTournament:
117    def __init__(self):117    def __init__(self):
118        self.name_to_egg = {}118        self.name_to_egg = {}
119        self.egg_to_name = {}119        self.egg_to_name = {}
120        self.wins = {}120        self.wins = {}
121121
122        self.battles = []122        self.battles = []
123123
124    def register(self, egg, name):124    def register(self, egg, name):
125        if egg.tournament is not None:125        if egg.tournament is not None:
126            raise ValueError("An egg cannot be registered in multiple tournaments")126            raise ValueError("An egg cannot be registered in multiple tournaments")
127127
128        if not name.isidentifier():128        if not name.isidentifier():
129            raise ValueError("Invalid registration name")129            raise ValueError("Invalid registration name")
130130
131        if name in self.name_to_egg:131        if name in self.name_to_egg:
132            raise ValueError(f"Egg with name {name} has already been registered")132            raise ValueError(f"Egg with name {name} has already been registered")
133133
134        self.name_to_egg[name] = egg134        self.name_to_egg[name] = egg
135        self.egg_to_name[egg] = name135        self.egg_to_name[egg] = name
136        self.wins[egg] = 0136        self.wins[egg] = 0
137        egg.tournament = self137        egg.tournament = self
138138
139    def _record_battle(self, egg1, egg2, side, winner):139    def _record_battle(self, egg1, egg2, side, winner):
140        if egg1 not in self.egg_to_name or egg2 not in self.egg_to_name:140        if egg1 not in self.egg_to_name or egg2 not in self.egg_to_name:
141            return141            return
142142
143        self.battles.append({143        self.battles.append({
144            "egg1": egg1,144            "egg1": egg1,
145            "egg2": egg2,145            "egg2": egg2,
146            "side": side,146            "side": side,
147            "winner": winner147            "winner": winner
148        })148        })
149149
150        self.wins[winner] += 1150        self.wins[winner] += 1
151151
152    def __getitem__(self, key):152    def __getitem__(self, key):
153        if isinstance(key, tuple):153        if isinstance(key, tuple):
154            if len(key) != 3:154            if len(key) != 3:
155                raise KeyError("Invalid key")155                raise KeyError("Invalid key")
156            egg1, egg2, side = key156            egg1, egg2, side = key
157        elif isinstance(key, slice):157        elif isinstance(key, slice):
158            egg1 = key.start158            egg1 = key.start
159            egg2 = key.stop159            egg2 = key.stop
160            side = key.step160            side = key.step
161        else:161        else:
162            raise KeyError("Invalid key")162            raise KeyError("Invalid key")
163163
164        if side not in ("top", "bottom"):164        if side not in ("top", "bottom"):
165            raise KeyError("Invalid key")165            raise KeyError("Invalid key")
166166
167        for battle in reversed(self.battles):167        for battle in reversed(self.battles):
168            same_pair = (168            same_pair = (
169                (battle["egg1"] is egg1 and battle["egg2"] is egg2) or169                (battle["egg1"] is egg1 and battle["egg2"] is egg2) or
170                (battle["egg1"] is egg2 and battle["egg2"] is egg1)170                (battle["egg1"] is egg2 and battle["egg2"] is egg1)
171            )171            )
172172
173            if same_pair and battle["side"] == side:173            if same_pair and battle["side"] == side:
174                return battle["winner"]174                return battle["winner"]
175175
176        raise KeyError("No such battle")176        raise KeyError("No such battle")
177177
178    def _get_positions(self):178    def _get_positions(self):
179        sorted_eggs = sorted(self.wins.items(), key=lambda pair: pair[1], reverse=True)179        sorted_eggs = sorted(self.wins.items(), key=lambda pair: pair[1], reverse=True)
180180
181        positions = {}181        positions = {}
182        current_position = 1182        current_position = 1
183183
184        for i in range(len(sorted_eggs)):184        for i in range(len(sorted_eggs)):
185            egg, wins = sorted_eggs[i]185            egg, wins = sorted_eggs[i]
186186
187            if i == 0:187            if i == 0:
188                positions[egg] = current_position188                positions[egg] = current_position
189            else:189            else:
190                previous_egg, previous_wins = sorted_eggs[i - 1]190                previous_egg, previous_wins = sorted_eggs[i - 1]
191191
192                if wins < previous_wins:192                if wins < previous_wins:
193                    current_position += 1193                    current_position += 1
194194
195                positions[egg] = current_position195                positions[egg] = current_position
196196
197        return positions197        return positions
198198
199    def __rmatmul__(self, place):199    def __rmatmul__(self, place):
200        positions = self._get_positions()200        positions = self._get_positions()
201        result = set()201        result = set()
202202
203        for egg, position in positions.items():203        for egg, position in positions.items():
204            if position == place:204            if position == place:
205                result.add(egg)205                result.add(egg)
206206
207        if len(result) == 0:207        if len(result) == 0:
208            raise IndexError("No eggs on this position")208            raise IndexError("No eggs on this position")
209209
210        if len(result) == 1:210        if len(result) == 1:
211            return next(iter(result))211            return next(iter(result))
212212
213        return result213        return result
214214
215    def __getattr__(self, name):215    def __getattr__(self, name):
216        if name in self.name_to_egg:216        if name in self.name_to_egg:
217            egg = self.name_to_egg[name]217            egg = self.name_to_egg[name]
218            positions = self._get_positions()218            positions = self._get_positions()
219219
220            return {220            return {
221                "position": positions[egg],221                "position": positions[egg],
222                "victories": self.wins[egg]222                "victories": self.wins[egg]
223            }223            }
224224
225        raise AttributeError("Apologies, there is no such egg registered")225        raise AttributeError("Apologies, there is no such egg registered")
226226
227    def __contains__(self, egg):227    def __contains__(self, egg):
228        return egg in self.egg_to_name228        return egg in self.egg_to_name
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op