Домашни > Великденско домашно > Решения > Решението на Калоян Иванов

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

7 точки общо

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

  1import re
  2class Egg:
  3    def __init__(self):
  4        self.paints = []
  5        self.total_percentage = 0.0
  6        self.broken_top = False
  7        self.broken_bottom = False
  8        self.tournament = None
  9
 10
 11    def paint(self, *args):
 12        current_sum = sum(p for _, p in args)
 13        if self.total_percentage + current_sum > 100.0:
 14            raise ValueError("Egg filling exceeds 100%")
 15
 16        for hex_color, percentage in args:
 17            self.paints.append((hex_color.upper(), percentage))
 18            self.total_percentage += percentage
 19    
 20
 21    def _get_strength(self, side):
 22        start_bound = 0.0 if side == 'top' else 50.0
 23        end_bound = 50.0 if side == 'top' else 100.0
 24        total_strength = 0.0
 25        current_offset = 0.0
 26        has_any_paint = False
 27        for hex_color, percentage in self.paints:
 28            color_start = current_offset
 29            color_end = current_offset + percentage
 30            overlap_start = max(color_start, start_bound)
 31            overlap_end = min(color_end, end_bound)
 32            if overlap_end > overlap_start:
 33                has_any_paint = True
 34                actual_p = overlap_end - overlap_start
 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                total_strength += (r + g + b) * (actual_p / 100.0)
 39            
 40            current_offset += percentage 
 41        if has_any_paint and total_strength == 0:
 42            return 1e-9           
 43        return total_strength
 44    
 45
 46    def _collide(self, other, side):
 47        if not isinstance(other, Egg):
 48            return NotImplemented
 49        if side == 'top':
 50            if self.broken_top: raise TypeError("Self egg top is broken")
 51            if other.broken_top: raise TypeError("Other egg top is broken")
 52        else:
 53            if self.broken_bottom: raise TypeError("Self egg bottom is broken")
 54            if other.broken_bottom: raise TypeError("Other egg bottom is broken")
 55        s1 = self._get_strength(side)
 56        s2 = other._get_strength(side)
 57
 58        winner = self if s1 > s2 else other
 59        loser = other if s1 > s2 else self
 60
 61        if side == 'top':
 62            loser.broken_top = True
 63        else:
 64            loser.broken_bottom = True
 65
 66        if self.tournament and other.tournament and self.tournament == other.tournament:
 67            self.tournament._record_match(self, other, side, winner)
 68
 69        return winner
 70    
 71
 72    def __mul__(self, other):
 73        return self._collide(other, 'top')
 74
 75    def __rmul__(self, other):
 76        return self._collide(other, 'top')
 77
 78    def __matmul__(self, other):
 79        return self._collide(other, 'bottom')
 80
 81    def __rmatmul__(self, other):
 82        return self._collide(other, 'bottom')
 83
 84
 85class EggTournament:
 86    def __init__(self):
 87        self.eggs = {}
 88        self.egg_to_name = {}
 89        self.matches = {}
 90        self.wins = {}
 91    
 92
 93    def register(self, egg, name):
 94        if not re.fullmatch(r'[a-zA-Z_][a-zA-Z0-9_]*', name):
 95            raise ValueError("Invalid registration name")
 96        if egg.tournament is not None:
 97            raise ValueError("An egg cannot be registered in multiple tournaments")
 98        if name in self.eggs:
 99            raise ValueError(f"Egg with name {name} has already been registered")
100
101        egg.tournament = self
102        self.eggs[name] = egg
103        self.egg_to_name[egg] = name
104        self.wins[egg] = 0
105
106
107    def _record_match(self, egg1, egg2, side, winner):
108        self.matches[(frozenset({egg1, egg2}), side)] = winner
109        self.wins[winner] += 1
110
111    
112    def __getitem__(self, key):
113        if isinstance(key, slice):
114            egg1, egg2, side = key.start, key.stop, key.step
115        else:
116            egg1, egg2, side = key
117            
118        match_key = (frozenset({egg1, egg2}), side)
119        if match_key not in self.matches:
120            raise KeyError("Match not found")
121        return self.matches[match_key]
122    
123
124    def _get_rankings(self):
125        sorted_eggs = sorted(self.wins.items(), key=lambda x: x[1], reverse=True)
126        ranks = {}
127        current_rank = 1
128        last_wins = -1
129
130        temp_ranks = []
131        for egg, win_count in sorted_eggs:
132            if win_count != last_wins:
133                if temp_ranks:
134                    current_rank += 1
135                last_wins = win_count
136            temp_ranks.append((egg, current_rank))
137
138        final_ranks = {}
139        for egg, r in temp_ranks:
140            final_ranks.setdefault(r, set()).add(egg)
141        return final_ranks
142    
143
144    def __rmatmul__(self, pos):
145        if not isinstance(pos, int):
146            return NotImplemented
147        rankings = self._get_rankings()
148        if pos not in rankings:
149            raise IndexError("Position not found in ranking")
150        res = rankings[pos]
151        return list(res)[0] if len(res) == 1 else res
152    
153
154    def __getattr__(self, name):
155        if name in self.eggs:
156            egg = self.eggs[name]
157            rankings = self._get_rankings()
158            pos = next(r for r, eggs in rankings.items() if egg in eggs)
159            return {"position": pos, "victories": self.wins[egg]}
160        raise AttributeError("Apologies, there is no such egg registered")
161
162
163    def __contains__(self, egg):
164        return egg in self.egg_to_name

..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.002s

OK

Дискусия
История
Това решение има само една версия.