1class Currency:
2 def __init__(self, name, rate):
3 self.name = name
4 self.rate = rate
5 def __eq__(self, other):
6 return self.name == other.name and self.rate == other.rate
7
8
9
10class PoliticalParty:
11 def __init__(self, name, motto, members=None, preferred_currency=None):
12 self.name = name
13 self._motto = motto
14 self.members = members if members is not None else []
15 self.preferred_currency = preferred_currency
16
17 @property
18 def motto(self):
19 return self._motto
20
21 def convert_currency_to_voters(self, amount, currency):
22 rate = currency.rate
23 if self.preferred_currency == currency:
24 rate = rate/2
25 return (amount // rate)
26
27 def add_party(self, other):
28 return Coalition(self, other)
29
30class Coalition:
31 def __init__(self, *parties):
32 self.parties = list(parties)
33
34 def get_members(self):
35 result = {}
36 for party in self.parties:
37 result[party.name] = party.members[:]
38 return result
39
40 def convert_currency_to_voters(self, amount, currency):
41 for party in self.parties:
42 if party.preferred_currency == currency:
43 return party.convert_currency_to_voters(amount, currency)
44 return (amount // currency.rate)
45
46 @property
47 def name(self):
48 names = []
49 for party in self.parties:
50 names.append(party.name)
51 return "-".join(names)
52
53 def add_party(self, other):
54 return Coalition(*self.parties, other)
55
56 def add_coalition(self, other):
57 return Coalition(*self.parties, *other.parties)
58
59class Elections:
60 all_results = {}
61
62 def __init__(self, year):
63 self.year = year
64 if year not in Elections.all_results:
65 Elections.all_results[year] = {}
66
67 def register_party_or_coalition(self, entity):
68 name = entity.name
69 if name not in Elections.all_results[self.year]:
70 Elections.all_results[self.year][name] = 0
71
72 def vote(self, entity):
73 name = entity.name
74 Elections.all_results[self.year][name] += 1
75
76 def rig_elections(self, entity, amount, currency):
77 name = entity.name
78 votes = entity.convert_currency_to_voters(amount, currency)
79 Elections.all_results[self.year][name] += votes
80
81 def get_results(self):
82 return Elections.all_results[self.year]
83 def get_results_by_year(self, year):
84 return Elections.all_results.get(year, {})
EE.EFEE.EFEEFEEE..E.F
======================================================================
ERROR: test_add_coalitions (test.TestCoalition.test_add_coalitions)
Adding two coalitions should return a new coalition containing all parties.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 116, in test_add_coalitions
new_coalition = coalition1 + coalition2
~~~~~~~~~~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for +: 'Coalition' and 'Coalition'
======================================================================
ERROR: test_add_party_to_coalition (test.TestCoalition.test_add_party_to_coalition)
Adding a party to a coalition should return a new coalition with all members preserved.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 104, in test_add_party_to_coalition
new_coalition = coalition + party3
~~~~~~~~~~^~~~~~~~
TypeError: unsupported operand type(s) for +: 'Coalition' and 'PoliticalParty'
======================================================================
ERROR: test_coalition_members_include_empty_lists (test.TestCoalition.test_coalition_members_include_empty_lists)
Coalition.members should return an empty list for parties without members.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 96, in test_coalition_members_include_empty_lists
self.assertEqual({"Party 1": [], "Party 2": ["a"]}, coalition.members)
^^^^^^^^^^^^^^^^^
AttributeError: 'Coalition' object has no attribute 'members'
======================================================================
ERROR: test_members (test.TestCoalition.test_members)
Coalition.members should return a mapping from party names to member lists.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 82, in test_members
self.assertEqual({"Party 1": ["a"], "Party 2": ["b"]}, coalition.members)
^^^^^^^^^^^^^^^^^
AttributeError: 'Coalition' object has no attribute 'members'
======================================================================
ERROR: test_party_addition_preserves_members (test.TestCoalition.test_party_addition_preserves_members)
Creating a coalition from two parties should preserve their members.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 88, in test_party_addition_preserves_members
coalition = party1 + party2
~~~~~~~^~~~~~~~
TypeError: unsupported operand type(s) for +: 'PoliticalParty' and 'PoliticalParty'
======================================================================
ERROR: test_get_results_by_year (test.TestElections.test_get_results_by_year)
get_results_by_year should return the results for the given election year.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 171, in test_get_results_by_year
self.assertEqual({"Party 1": 1}, Elections.get_results_by_year(2026))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
TypeError: Elections.get_results_by_year() missing 1 required positional argument: 'year'
======================================================================
ERROR: test_rig_elections (test.TestElections.test_rig_elections)
rig_elections should add as many bought votes as possible to the result.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 157, in test_rig_elections
self.elections_2026.rig_elections(self.party, 50, self.currency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in rig_elections
votes = entity.convert_currency_to_voters(amount, currency)
File "/tmp/solution.py", line 23, in convert_currency_to_voters
if self.preferred_currency == currency:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 6, in __eq__
return self.name == other.name and self.rate == other.rate
^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'
======================================================================
ERROR: test_rig_elections_preferred_currency (test.TestElections.test_rig_elections_preferred_currency)
rig_elections should use the most effective preferred currency conversion in a coalition.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 163, in test_rig_elections_preferred_currency
self.elections_2026.rig_elections(self.coalition, 80, self.currency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 78, in rig_elections
votes = entity.convert_currency_to_voters(amount, currency)
File "/tmp/solution.py", line 42, in convert_currency_to_voters
if party.preferred_currency == currency:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 6, in __eq__
return self.name == other.name and self.rate == other.rate
^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'
======================================================================
ERROR: test_convert_currency_to_voters (test.TestPoliticalParty.test_convert_currency_to_voters)
convert_currency_to_voters should return normal or double voters depending on the preferred currency.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 42, in test_convert_currency_to_voters
self.assertEqual(4, self.party.convert_currency_to_voters(34, self.currency))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 23, in convert_currency_to_voters
if self.preferred_currency == currency:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 6, in __eq__
return self.name == other.name and self.rate == other.rate
^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'
======================================================================
ERROR: test_convert_currency_to_voters_floating_point_edge_case (test.TestPoliticalParty.test_convert_currency_to_voters_floating_point_edge_case)
convert_currency_to_voters should properly account for floating point edge cases (e.g. 0.200001 errors).
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 55, in test_convert_currency_to_voters_floating_point_edge_case
self.assertEqual(5, party.convert_currency_to_voters(2, currency))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "/tmp/solution.py", line 23, in convert_currency_to_voters
if self.preferred_currency == currency:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 6, in __eq__
return self.name == other.name and self.rate == other.rate
^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'
======================================================================
ERROR: test_convert_currency_to_voters_rounding (test.TestPoliticalParty.test_convert_currency_to_voters_rounding)
convert_currency_to_voters should round the number of voters down.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 49, in test_convert_currency_to_voters_rounding
self.assertEqual(4, self.party.convert_currency_to_voters(34.5, self.currency))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 23, in convert_currency_to_voters
if self.preferred_currency == currency:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 6, in __eq__
return self.name == other.name and self.rate == other.rate
^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'
======================================================================
ERROR: test_party_addition (test.TestPoliticalParty.test_party_addition)
Adding two parties should create a Coalition.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 65, in test_party_addition
coalition = party1 + party2
~~~~~~~^~~~~~~~
TypeError: unsupported operand type(s) for +: 'PoliticalParty' and 'PoliticalParty'
======================================================================
FAIL: test_coalition_str (test.TestCoalition.test_coalition_str)
Coalition should convert to a dash-separated list of party names.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 128, in test_coalition_str
self.assertEqual("Party 1-Party 2", str(coalition))
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 'Party 1-Party 2' != '<solution.Coalition object at 0x7e5165aab2f0>'
- Party 1-Party 2
+ <solution.Coalition object at 0x7e5165aab2f0>
======================================================================
FAIL: test_register_party_or_coalition_starts_with_zero_votes (test.TestElections.test_register_party_or_coalition_starts_with_zero_votes)
Registered parties and coalitions should start with zero votes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 152, in test_register_party_or_coalition_starts_with_zero_votes
self.assertEqual({"Party 1": 0}, self.elections_2026.get_results())
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: {'Party 1': 0} != {'Party 1': 1}
- {'Party 1': 0}
? ^
+ {'Party 1': 1}
? ^
======================================================================
FAIL: test_vote (test.TestElections.test_vote)
vote should add one vote to the given registered party or coalition.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 147, in test_vote
self.assertEqual({"Party 1": 2, "Party 2-Party 3": 1}, self.elections_2026.get_results())
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: {'Party 1': 2, 'Party 2-Party 3': 1} != {'Party 1': 3, 'Party 2-Party 3': 1}
- {'Party 1': 2, 'Party 2-Party 3': 1}
? ^
+ {'Party 1': 3, 'Party 2-Party 3': 1}
? ^
======================================================================
FAIL: test_party_str (test.TestPoliticalParty.test_party_str)
PoliticalParty should convert to its name when cast to string.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 59, in test_party_str
self.assertEqual("Some Name", str(self.party))
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 'Some Name' != '<solution.PoliticalParty object at 0x7e5165aad080>'
- Some Name
+ <solution.PoliticalParty object at 0x7e5165aad080>
----------------------------------------------------------------------
Ran 21 tests in 0.005s
FAILED (failures=4, errors=12)
Виктор Бечев
25.03.2026 13:20Получаваш поощрителна бонус точка, защото въпреки очевидния проблем със събирането на партии и коалиции, кодът ти е добре написан и работи.
Получаваш още една бонус точка, защото си добавил хубава абстракция под формата на `Coallition.convert_currency_to_voters`.
|
25.03.2026 13:16
25.03.2026 13:16
25.03.2026 13:18
25.03.2026 13:19