1class Currency:
2 def __init__(self, name, rate):
3 self.name = name
4 self.rate = rate
5
6 def __eq__(self, other):
7 if not isinstance(other, Currency):
8 return NotImplemented
9 return self.name == other.name and self.rate == other.rate
10
11 def __repr__(self):
12 return f"Currency({self.name!r}, {self.rate})"
13
14
15class PoliticalParty:
16 def __init__(self, name, motto, members=None, preferred_currency=None):
17 self.name = name
18 self._motto = motto
19 self.members = members or []
20 self.preferred_currency = preferred_currency
21
22 @property
23 def motto(self):
24 return self._motto
25
26 @motto.setter
27 def motto(self, value):
28 raise AttributeError("Девизът не може да бъде променян!")
29
30 def convert_currency_to_voters(self, amount, currency):
31 votes = int(amount / currency.rate)
32 if self.preferred_currency and currency == self.preferred_currency:
33 votes *= 2
34 return votes
35
36 def __str__(self):
37 return self.name
38
39 def __repr__(self):
40 return f"PoliticalParty({self.name!r})"
41
42 def __add__(self, other):
43 if isinstance(other, PoliticalParty):
44 return Coalition(self, other)
45 if isinstance(other, Coalition):
46 return Coalition(self, *other._parties)
47 return NotImplemented
48
49
50class Coalition:
51 def __init__(self, *parties):
52 # Each argument may be a PoliticalParty or another Coalition;
53 # flatten everything into an ordered list of PoliticalParty objects.
54 self._parties = []
55 for item in parties:
56 if isinstance(item, PoliticalParty):
57 self._parties.append(item)
58 elif isinstance(item, Coalition):
59 self._parties.extend(item._parties)
60 else:
61 raise TypeError(f"Expected PoliticalParty or Coalition, got {type(item)}")
62
63 @property
64 def members(self):
65 return {party.name: list(party.members) for party in self._parties}
66
67 def __str__(self):
68 return "-".join(party.name for party in self._parties)
69
70 def __repr__(self):
71 return f"Coalition({str(self)!r})"
72
73 def __add__(self, other):
74 if isinstance(other, PoliticalParty):
75 return Coalition(*self._parties, other)
76 if isinstance(other, Coalition):
77 return Coalition(*self._parties, *other._parties)
78 return NotImplemented
79
80
81class Elections:
82 # Class-level registry: {year: Elections instance}
83 _registry = {}
84
85 def __init__(self, year):
86 self.year = year
87 # {str(party_or_coalition): {"entity": ..., "votes": int}}
88 self._entries = {}
89 Elections._registry[year] = self
90
91 def _key(self, entity):
92 return str(entity)
93
94 def register_party_or_coalition(self, entity):
95 key = self._key(entity)
96 if key not in self._entries:
97 self._entries[key] = {"entity": entity, "votes": 0}
98
99 def vote(self, entity):
100 key = self._key(entity)
101 if key not in self._entries:
102 raise ValueError(f"{entity!r} is not registered in these elections")
103 self._entries[key]["votes"] += 1
104
105 def rig_elections(self, entity, amount, currency):
106 key = self._key(entity)
107 if key not in self._entries:
108 raise ValueError(f"{entity!r} is not registered in these elections")
109 entity_obj = self._entries[key]["entity"]
110
111 # For a coalition: pick the member party that yields the most votes for
112 # this currency (a party with a matching preferred_currency gets a 2x bonus),
113 # then credit the winning count to the coalition.
114 if isinstance(entity_obj, Coalition):
115 best_votes = 0
116 for party in entity_obj._parties:
117 votes = party.convert_currency_to_voters(amount, currency)
118 if votes > best_votes:
119 best_votes = votes
120 self._entries[key]["votes"] += best_votes
121 else:
122 # It's a PoliticalParty
123 self._entries[key]["votes"] += entity_obj.convert_currency_to_voters(amount, currency)
124
125 def get_results(self):
126 return {key: data["votes"] for key, data in self._entries.items()}
127
128 @classmethod
129 def get_results_by_year(cls, year):
130 if year not in cls._registry:
131 return {}
132 return cls._registry[year].get_results()
133
134
135# ---------------------------------------------------------------------------
136# Quick smoke tests — run with: python elections.py
137# ---------------------------------------------------------------------------
138if __name__ == "__main__":
139 # Currency equality
140 kebapcheta = Currency("кебапчета", 15)
141 pak_kebapcheta = Currency("кебапчета", 15)
142 gadni_kebapcheta = Currency("кебапчета", 35)
143 evra = Currency("евро", 35)
144
145 assert kebapcheta == pak_kebapcheta, "Should be equal"
146 assert not (kebapcheta == gadni_kebapcheta), "Should differ"
147 assert not (gadni_kebapcheta == evra), "Should differ"
148 print("Currency equality: OK")
149
150 # Motto read-only
151 GERB_test = PoliticalParty("ГЕРБ", "Ту-тууу!")
152 assert GERB_test.motto == "Ту-тууу!"
153 try:
154 GERB_test.motto = "Нещо друго"
155 assert False, "Should have raised"
156 except AttributeError:
157 pass
158 print("Motto read-only: OK")
159
160 # convert_currency_to_voters
161 leva = Currency("левчета", 50)
162 SDS_test = PoliticalParty("СДС", "Ние също сме шокирани...")
163 greatness = PoliticalParty("Величие", "Не на еврото!", preferred_currency=leva)
164 assert SDS_test.convert_currency_to_voters(100, leva) == 2
165 assert greatness.convert_currency_to_voters(100, leva) == 4
166
167 kebapcheta2 = Currency("кебапчета", 15)
168 DPS = PoliticalParty("ДПС", "КТБ по КТБ...", preferred_currency=kebapcheta2)
169 assert DPS.convert_currency_to_voters(50, kebapcheta2) == 6
170 print("convert_currency_to_voters: OK")
171
172 # Coalition basics
173 yes_Bulgaria = PoliticalParty("Да, България", "Ще щурмуваме...",
174 members=["Божо", "Ивайло Мирчев"])
175 DSB = PoliticalParty("ДСБ", "Помните ли Иван Костов?",
176 members=["Не-Иван-Костов", "Пак не е Иван Костов"])
177 DB = Coalition(yes_Bulgaria, DSB)
178 assert DB.members == {
179 "Да, България": ["Божо", "Ивайло Мирчев"],
180 "ДСБ": ["Не-Иван-Костов", "Пак не е Иван Костов"],
181 }
182 print("Coalition.members: OK")
183
184 # Coalition + Party
185 PP = PoliticalParty("ПП", "Не сме сигурни...", members=["Асенката"])
186 PPDB = DB + PP
187 assert list(PPDB.members.keys()) == ["Да, България", "ДСБ", "ПП"]
188 assert str(PPDB) == "Да, България-ДСБ-ПП"
189 print("Coalition + Party: OK")
190
191 # Coalition + Coalition
192 GERB2 = PoliticalParty("ГЕРБ", "Ту-тууу!", members=["Бат'", "Бойко", "и", "сам", "стига"])
193 SDS2 = PoliticalParty("СДС", "Ние също...", members=["Румен, ама не Радев"])
194 GERB_SDS = GERB2 + SDS2
195 OMG = DB + GERB_SDS
196 assert list(OMG.members.keys()) == ["Да, България", "ДСБ", "ГЕРБ", "СДС"]
197 print("Coalition + Coalition: OK")
198
199 # Elections full example
200 elections_2026 = Elections(2026)
201
202 BSP = PoliticalParty("БСП", "Ще вдигнем пенсиите и тази година!",
203 members=["Крум Еди-Кой-Си", "Атанас Еди-Кой-Си", "Онзи другия"])
204 elections_2026.register_party_or_coalition(BSP)
205
206 gold_bars = Currency("мини-златни кюлчета", 0.2)
207 GERB3 = PoliticalParty("ГЕРБ", "Ту-тууу!",
208 members=["Бат'", "Бойко", "и", "сам", "стига"],
209 preferred_currency=gold_bars)
210 SDS3 = PoliticalParty("СДС", "Ние също сме шокирани...",
211 members=["Румен, ама не Радев"])
212 GERB_SDS2 = GERB3 + SDS3
213
214 elections_2026.register_party_or_coalition(GERB_SDS2)
215 elections_2026.vote(BSP)
216 elections_2026.rig_elections(GERB_SDS2, 1, gold_bars)
217
218 results = elections_2026.get_results()
219 assert results == {"БСП": 1, "ГЕРБ-СДС": 10}, f"Got: {results}"
220 print("Elections full example: OK")
221
222 print("\nВсички тестове минаха успешно!")
.....................
----------------------------------------------------------------------
Ran 21 tests in 0.001s
OK
Боян Байданов
25.03.2026 13:05Смятам че решението се е получило добре, защото изискванията на задачата са много добре разписани. При по-неясни условия опита ми показва, че бота няма да се справи толкова добре.
|
Виктор Бечев
25.03.2026 12:40Отвъд горните коментари - притеснително приличен код. :grin:
|
Виктор Бечев
25.03.2026 12:35Мерси за чесността, точки няма да получиш, ама на теб така или иначе за точките ти е все тая. ☺️
|
Боян Байданов
24.03.2026 22:41Малко нямах време и го направих с Claude Code. Напълно ок съм да не получа точки или човешка проверка, а само да видя дали ще мине автоматичните тестове.
|
25.03.2026 12:38
25.03.2026 12:37
25.03.2026 12:35