Домашни > Предизборно ООП


Предизборно ООП
Краен срок: 24.03.2026 23:59
Точки: 7

Вдъхновени от предстоящите _(поредни)_ парламентарни избори, решихме да ви помолим заедно да подготвим симулация на изборния процес. **Бел. Ред. - Да**, знаем, че нямате търпение за картинката, която неизменно върви с домашните, обещаваме да си я получите по някое време. Но тъй като това е предизборно обещание, може да го спазим, може и да не го спазим. Обратно към домашното! За да _"симулираме"_ парламентарните избори ще са ни необходими няколко неща: #### `Currency` Напишете клас `Currency`, който да ни помогне да дефинираме различните валути, с които партиите могат да си купвуат избиратели. Искаме класът да приема два аргумента - име и "курс" на валутата, т.е. колко от дадената валута е нужна за купуване на един глас. Пример: ``` kebapcheta = Currency("кебапчета", 15) ``` ##### Сравнение на `Currency` Искаме да можем да сравняваме валути с `==` - една единица е равна на друга, ако имената **и** "курсът" на двете са еднакви! ``` kebapcheta = Currency("кебапчета", 15) pak_kebapcheta = Currency("кебапчета", 15) gadni_kebapcheta = Currency("кебапчета", 35) evra = Currency("евро", 35) print(kebapcheta == pak_kebapcheta) # True print(kebapcheta == gadni_kebapcheta) # False print(gadni_kebapcheta == evra) # False ``` #### `PoliticalParty` Напишете клас `PoliticalParty`, който да ни помогне да дефинираме понятието "партия". Искаме класът да приема следните аргументи: - Първи позиционен аргумент - име на партията. - Втори позиционен аргумент - девиз на партията. - Опционален аргумент `members`, който е *списък* от членове на партията. - Опционален аргумент `preferred_currency`, който показва предпочитаната от потенциалните избиратели на тази партия валута. Примери: ``` rebirth = PoliticalParty("Възраждане", "Аман от тия гей паради!") BSP = PoliticalParty("БСП", "Ще вдигнем пенсиите и тази година!", members=["Крум Еди-Кой-Си", "Атанас Еди-Кой-Си", "Онзи другия"]) # preferred_currency gold_bars = Currency("мини-златни кюлчета", 0.2) GERB = PoliticalParty("ГЕРБ", "Ту-тууу!", preferred_currency=gold_bars) ``` ##### Девиз Искаме девизът да е достъпен чрез атрибута `party.motto`, но само за четене. Т.е. искаме да забраним това девизът да бъде променян чрез външен за класа достъп. ``` GERB = PoliticalParty("ГЕРБ", "Ту-тууу!") print(GERB.motto) # "Ту-тууу!" GERB.motto = "Дайте пак да се пробваме?" # ТЦ! Не може! Грешка. ``` ##### `convert_currency_to_voters` Искаме методът на `PoliticalParty` - `convert_currency_to_voters` да конвертира даден брой единици от дадена валута в брой избиратели. Ако това е предпочитаната единица на въпросната партия, ефективността ѝ се удвоява и тя може да закупи двойно повече гласове. Например: ``` leva = Currency("левчета", 50) SDS = PoliticalParty("СДС", "Ние също сме шокирани, че все още съществуваме...") greatness = PoliticalParty("Величие", "Не на еврото!", preferred_currency=leva) print(SDS.convert_currency_to_voters(100, leva)) # 2 print(greatness.convert_currency_to_voters(100, leva)) # 4 ``` Ако с дадената бройка единици от валутата не могат да се купят кръгло число гласове - купуват се колкото може и ресто не се връща _(да са си правили сметката)_: ``` kebapcheta = Currency("кебапчета", 15) DPS = PoliticalParty("ДПС", "КТБ по КТБ - знаете...", preferred_currency=kebapcheta) print(DPS.convert_currency_to_voters(50, kebapcheta)) # 6, останалите 5 кебапчета са бакшиш ``` ##### Стрингова репрезентация на `PoliticalParty` Искаме да дефинираме поведение при конвертиране към `str` за нашите партии. Страшно е просто - това са просто имената на партиите: ``` SDS = PoliticalParty("СДС", "Ние също сме шокирани, че все още съществуваме...") print(str(SDS)) # "СДС" # Бонус - print функцията прави конвертирането автоматично: print(SDS) # "СДС" ``` ##### Коалиране Както добре знаем, партиите могат да се коалират по неочаквани за нас начини. В нашето задание искаме да го дефинираме с минимален интерфейс - `+`. Когато две партии бъдат "събрани", те сформират нова инстанция на обект `Coalition`. Например: ``` GERB = PoliticalParty("ГЕРБ", "Ту-тууу!") SDS = PoliticalParty("СДС", "Ние също сме шокирани, че все още съществуваме...") GERB_SDS = GERB + SDS print(type(GERB_SDS)) # <__main__.Coalition object ...> ``` А що се отнася до `Coalition`... #### `Coalition` Напишете клас `Coalition`, който репрезентира коалиция от партии (предизборна коалиция). За начало, искаме да може да се инициализира с произволен брой `PoliticalParty` обекти: ``` yes_Bulgaria = PoliticalParty("Да, България", "Ще щурмуваме всичко на север от Одрин!") # Добре де, Христо Иванов вече го няма, но Божо има много точки в Stack Overflow и него не можем да нападаме DSB = PoliticalParty("ДСБ", "Помните ли Иван Костов?") DB = Coalition(yes_Bulgaria, DSB) ``` ##### `members` Искаме коалициите да имат атрибут `members`, който да ни дава речник състоящ се от имената на партиите, участващи в коалицията, като ключове, и списъци с техните членове като стойности: ``` yes_Bulgaria = PoliticalParty("Да, България", "Ще щурмуваме всичко на север от Одрин!", members=["Божо", "Ивайло Мирчев"]) DSB = PoliticalParty("ДСБ", "Помните ли Иван Костов?", members=["Не-Иван-Костов", "Пак не е Иван Костов"]) DB = Coalition(yes_Bulgaria, DSB) print(DB.members) # {"Да, България": ["Божо", "Ивайло Мирчев"], "ДСБ": ["Не-Иван-Костов", "Пак не е Иван Костов"]} ``` - **Уговорка**: Ако дадена партия не е създадена с `members=[...]`, т.е. списъкът с членове е празен, и тя участва в коалиция, то `Coalition.members` връща **празен списък** за въпросната партия. ##### Събиране на партии / коалиции Искаме възможността да добавяме партии или сливаме коалиции по следния начин: ``` yes_Bulgaria = PoliticalParty("Да, България", "Ще щурмуваме всичко на север от Одрин!", members=["Божо", "Ивайло Мирчев"]) DSB = PoliticalParty("ДСБ", "Помните ли Иван Костов?", members=["Не-Иван-Костов", "Пак не е Иван Костов"]) DB = Coalition(yes_Bulgaria, DSB) PP = PoliticalParty("ПП", "Не сме сигурни все още...", members=["Асенката"]) PPDB = DB + PP print(PPDB.members) # {"Да, България": ["Божо", "Ивайло Мирчев"], "ДСБ": ["Не-Иван-Костов", "Пак не е Иван Костов"], "ПП": ["Асенката"]} ``` С други думи добавянето на партия към коалиция връща нова коалиция, която съдържа информацията за партиите от коалицията + новодобавената партия. За да улесним нещата, ще имплементираме само поведението `Coalition + PoliticalParty`, но не и `PoliticalParty + Coalition` _(да, има разлика)_. Същото правило важи и за събиране на две коалиции: ``` yes_Bulgaria = PoliticalParty("Да, България", "Ще щурмуваме всичко на север от Одрин!", members=["Божо", "Ивайло Мирчев"]) DSB = PoliticalParty("ДСБ", "Помните ли Иван Костов?", members=["Не-Иван-Костов", "Пак не е Иван Костов"]) DB = Coalition(yes_Bulgaria, DSB) GERB = PoliticalParty("ГЕРБ", "Ту-тууу!", members=["Бат'", "Бойко", "и", "сам", "стига"]) SDS = PoliticalParty("СДС", "Ние също сме шокирани, че все още съществуваме...", members=["Румен, ама не Радев"]) GERB_SDS = GERB + SDS OMG = DB + GERB_SDS print(OMG.members) # {"Да, България": ["Божо", "Ивайло Мирчев"], "ДСБ": ["Не-Иван-Костов", "Пак не е Иван Костов"], "ГЕРБ": ["Бат'", "Бойко", "и", "сам", "стига"], "СДС": ["Румен, ама не Радев"]} ``` Мислехме да ви тормозим и с премахване на партии от коалиция, но решихме, че много ще ескалираме домашното ако трябва да имплементирате и сбивания в народното събрание. ##### Стрингова репрезентация на `Coalition` Искаме да дефинираме поведение при конвертиране към `str` за нашите коалиции. Резултатът от това ще е конкатенация на имената на партиите в реда на добавянето им, разделени от `"-"` _(тире)_. Пример: ``` PPDB = DB + PP print(str(PPDB)) # "Да, България-ДСБ-ПП" ``` #### `Elections` И финално, искаме клас `Elections`, който да се грижи за провеждането на изборите. Инициализацията става с един позиционен аргумент, който е година на провеждане. Отвъд това, искаме следните той да има следните методи: - `register_party_or_coalition` - приема партия или коалиция и я регистрира като участваща в тазгодишните избори - `vote` - приема партия или коалиция и добавя един глас към гласовете за нея - `rig_elections` - приема партия или коалиция, количество и валута и купува колкото е възможно повече гласове, добавяйки ги към общия резултат за тази партия или коалиция. **Забележка**: Ако става въпрос за коалиция, добре е да потърсите дали случайно това не е предпочитана единица за някоя от партиите и да "купите" чрез нейният метод за конвертиране на валута в гласоподаватели, защото това е начинът да купите "колкото е възможно повече". - `get_results` - връща резултатите от изборите във формата на речник, където ключовете са имена на партии или коалици (името на коалицията е нейната стрингова репрезентация), а стойностите - гласове за дадената партия или коалиция - `get_results_by_year` - връща резултати за изборите проведени в дадена година **Уточнение** - когато се гласува за коалиция, гласовете се броят само за тази коалиция. Опростен вариант на реалното гласуване, но не искаме да броим и двете. С други думи **няма** да тестваме с добавяне на коалиция и отделно партия, която е част от същата коалиция към `Elections`. ###### Обобщен пример за изборите ``` elections_2026 = Elections(2026) BSP = PoliticalParty("БСП", "Ще вдигнем пенсиите и тази година!", members=["Крум Еди-Кой-Си", "Атанас Еди-Кой-Си", "Онзи другия"]) elections_2026.register_party_or_coalition(BSP) gold_bars = Currency("мини-златни кюлчета", 0.2) GERB = PoliticalParty("ГЕРБ", "Ту-тууу!", members=["Бат'", "Бойко", "и", "сам", "стига"], preferred_currency=gold_bars) SDS = PoliticalParty("СДС", "Ние също сме шокирани, че все още съществуваме...", members=["Румен, ама не Радев"]) GERB_SDS = GERB + SDS elections_2026.register_party_or_coalition(GERB_SDS) elections_2026.vote(BSP) elections_2026.rig_elections(GERB_SDS, 1, gold_bars) print(elections_2026.get_results()) # {"БСП": 1, "ГЕРБ-СДС": 10} # Не сме ги дефинирали тук, но все пак print(Elections.get_results_by_year(2025)) # Някакви други резултати, защото са за 2025 ``` И финална **уговорка** - няма да правим повече от едни избори в една и съща година... Така де, поне за нашите цели - няма.
 1import unittest
 2
 3import solution
 4
 5
 6class TestSanity(unittest.TestCase):
 7    """Check if all data is present."""
 8
 9    def test_requirements(self):
10        names = ["Currency", "PoliticalParty", "Coalition", "Elections"]
11        unimported = [name for name in names if name not in dir(solution)]
12        self.assertEqual(
13            unimported, [], "\n\nЕлементите по-горе липсват (проверете си имената)!"
14        )
15
16
17if __name__ == "__main__":
18    unittest.main()
  1import unittest
  2
  3from solution import *
  4
  5
  6class TestCurrency(unittest.TestCase):
  7    def test_currency_equals(self):
  8        """Currency elements should be equal when their name and "rate" is the same."""
  9        cur1 = Currency("something", 5)
 10        cur2 = Currency("something", 5)
 11        cur3 = Currency("something", 10)
 12        cur4 = Currency("something_else", 5)
 13        cur5 = Currency("something_completely_else", 20)
 14        self.assertEqual(cur1, cur2)
 15        self.assertNotEqual(cur1, cur3)
 16        self.assertNotEqual(cur1, cur4)
 17        self.assertNotEqual(cur1, cur5)
 18
 19
 20class TestPoliticalParty(unittest.TestCase):
 21    def setUp(self):
 22        self.party = PoliticalParty("Some Name", "Some motto")
 23        self.currency = Currency("something", 8.5)
 24
 25    def test_party_init(self):
 26        """PoliticalParty should support initialization with optional members and preferred currency."""
 27        PoliticalParty("Some Name", "Some motto")
 28        PoliticalParty("Some Name", "Some motto", members=["a", "b", "c"])
 29        PoliticalParty("Some Name", "Some motto", preferred_currency=Currency("something", 10))
 30
 31    def test_motto(self):
 32        """Motto should be accessible with the PoliticalParty.motto attribute."""
 33        self.assertEqual("Some motto", self.party.motto)
 34
 35    def test_motto_write(self):
 36        """Motto should not be writable after the party is created."""
 37        with self.assertRaises(Exception):
 38            self.party.motto = "some other motto"  # type: ignore
 39
 40    def test_convert_currency_to_voters(self):
 41        """convert_currency_to_voters should return normal or double voters depending on the preferred currency."""
 42        self.assertEqual(4, self.party.convert_currency_to_voters(34, self.currency))
 43
 44        party_with_cur = PoliticalParty("Some Name", "Some motto", preferred_currency=self.currency)
 45        self.assertEqual(8, party_with_cur.convert_currency_to_voters(34, self.currency))
 46
 47    def test_convert_currency_to_voters_rounding(self):
 48        """convert_currency_to_voters should round the number of voters down."""
 49        self.assertEqual(4, self.party.convert_currency_to_voters(34.5, self.currency))
 50
 51    def test_convert_currency_to_voters_floating_point_edge_case(self):
 52        """convert_currency_to_voters should properly account for floating point edge cases (e.g. 0.200001 errors)."""
 53        party = PoliticalParty("Some Name", "Some motto")
 54        currency = Currency("something", 0.4)
 55        self.assertEqual(5, party.convert_currency_to_voters(2, currency))
 56
 57    def test_party_str(self):
 58        """PoliticalParty should convert to its name when cast to string."""
 59        self.assertEqual("Some Name", str(self.party))
 60
 61    def test_party_addition(self):
 62        """Adding two parties should create a Coalition."""
 63        party1 = PoliticalParty("Party 1", "Some motto", members=["a", "b"])
 64        party2 = PoliticalParty("Party 2", "Some motto", members=["c"])
 65        coalition = party1 + party2
 66        self.assertIsInstance(coalition, Coalition)
 67
 68
 69class TestCoalition(unittest.TestCase):
 70    def test_coalition_init_with_multiple(self):
 71        """Coalition should support initialization with multiple parties."""
 72        party1 = PoliticalParty("Party 1", "Motto 1")
 73        party2 = PoliticalParty("Party 2", "Motto 2")
 74        party3 = PoliticalParty("Party 3", "Motto 3")
 75        Coalition(party1, party2, party3)
 76
 77    def test_members(self):
 78        """Coalition.members should return a mapping from party names to member lists."""
 79        party1 = PoliticalParty("Party 1", "Motto 1", members=["a"])
 80        party2 = PoliticalParty("Party 2", "Motto 2", members=["b"])
 81        coalition = Coalition(party1, party2)
 82        self.assertEqual({"Party 1": ["a"], "Party 2": ["b"]}, coalition.members)
 83
 84    def test_party_addition_preserves_members(self):
 85        """Creating a coalition from two parties should preserve their members."""
 86        party1 = PoliticalParty("Party 1", "Motto 1", members=["a"])
 87        party2 = PoliticalParty("Party 2", "Motto 2", members=["b"])
 88        coalition = party1 + party2
 89        self.assertEqual({"Party 1": ["a"], "Party 2": ["b"]}, coalition.members)
 90
 91    def test_coalition_members_include_empty_lists(self):
 92        """Coalition.members should return an empty list for parties without members."""
 93        party1 = PoliticalParty("Party 1", "Motto 1")
 94        party2 = PoliticalParty("Party 2", "Motto 2", members=["a"])
 95        coalition = Coalition(party1, party2)
 96        self.assertEqual({"Party 1": [], "Party 2": ["a"]}, coalition.members)
 97
 98    def test_add_party_to_coalition(self):
 99        """Adding a party to a coalition should return a new coalition with all members preserved."""
100        party1 = PoliticalParty("Party 1", "Motto 1", members=["a"])
101        party2 = PoliticalParty("Party 2", "Motto 2", members=["b"])
102        party3 = PoliticalParty("Party 3", "Motto 3", members=["c"])
103        coalition = Coalition(party1, party2)
104        new_coalition = coalition + party3
105        self.assertEqual({"Party 1": ["a"], "Party 2": ["b"], "Party 3": ["c"]}, new_coalition.members)
106        self.assertIsNot(new_coalition, coalition)
107
108    def test_add_coalitions(self):
109        """Adding two coalitions should return a new coalition containing all parties."""
110        party1 = PoliticalParty("Party 1", "Motto 1", members=["a"])
111        party2 = PoliticalParty("Party 2", "Motto 2", members=["b"])
112        party3 = PoliticalParty("Party 3", "Motto 3", members=["c"])
113        party4 = PoliticalParty("Party 4", "Motto 4", members=["d"])
114        coalition1 = Coalition(party1, party2)
115        coalition2 = Coalition(party3, party4)
116        new_coalition = coalition1 + coalition2
117        self.assertEqual(
118            {"Party 1": ["a"], "Party 2": ["b"], "Party 3": ["c"], "Party 4": ["d"]}, new_coalition.members
119        )
120        self.assertIsNot(new_coalition, coalition1)
121        self.assertIsNot(new_coalition, coalition2)
122
123    def test_coalition_str(self):
124        """Coalition should convert to a dash-separated list of party names."""
125        party1 = PoliticalParty("Party 1", "Motto 1", members=["a"])
126        party2 = PoliticalParty("Party 2", "Motto 2", members=["b"])
127        coalition = Coalition(party1, party2)
128        self.assertEqual("Party 1-Party 2", str(coalition))
129
130
131class TestElections(unittest.TestCase):
132    def setUp(self):
133        self.currency = Currency("something", 10)
134        self.party = PoliticalParty("Party 1", "Motto 1", members=["a"])
135        party2 = PoliticalParty("Party 2", "Motto 2", members=["b"])
136        party3 = PoliticalParty("Party 3", "Motto 3", members=["c"], preferred_currency=self.currency)
137        self.coalition = Coalition(party2, party3)
138        self.elections_2026 = Elections(2026)
139
140    def test_vote(self):
141        """vote should add one vote to the given registered party or coalition."""
142        self.elections_2026.register_party_or_coalition(self.party)
143        self.elections_2026.register_party_or_coalition(self.coalition)
144        self.elections_2026.vote(self.party)
145        self.elections_2026.vote(self.party)
146        self.elections_2026.vote(self.coalition)
147        self.assertEqual({"Party 1": 2, "Party 2-Party 3": 1}, self.elections_2026.get_results())
148
149    def test_register_party_or_coalition_starts_with_zero_votes(self):
150        """Registered parties and coalitions should start with zero votes."""
151        self.elections_2026.register_party_or_coalition(self.party)
152        self.assertEqual({"Party 1": 0}, self.elections_2026.get_results())
153
154    def test_rig_elections(self):
155        """rig_elections should add as many bought votes as possible to the result."""
156        self.elections_2026.register_party_or_coalition(self.party)
157        self.elections_2026.rig_elections(self.party, 50, self.currency)
158        self.assertEqual({"Party 1": 5}, self.elections_2026.get_results())
159
160    def test_rig_elections_preferred_currency(self):
161        """rig_elections should use the most effective preferred currency conversion in a coalition."""
162        self.elections_2026.register_party_or_coalition(self.coalition)
163        self.elections_2026.rig_elections(self.coalition, 80, self.currency)
164        self.elections_2026.rig_elections(self.coalition, 50, Currency("something else", 10))
165        self.assertEqual({"Party 2-Party 3": 21}, self.elections_2026.get_results())
166
167    def test_get_results_by_year(self):
168        """get_results_by_year should return the results for the given election year."""
169        self.elections_2026.register_party_or_coalition(self.party)
170        self.elections_2026.vote(self.party)
171        self.assertEqual({"Party 1": 1}, Elections.get_results_by_year(2026))
172
173
174if __name__ == "__main__":
175    unittest.main()
Дискусия
Гергана Панделиева
25.03.2026 00:02

Бях влезнала съм в профила си и в 23:50(ясно е, че не трябваше да чакам последния момент) не ми даваше възможност да си прикача домашното, а до сега не ми беше създавало проблем.
Николай Георгиев
24.03.2026 18:11

Трябва ли да проверявам в register_party_or_coalition() или въобще някъде в Elections дали някоя партия не е станала твърде алчна и освен че участва сама в изборите, е и част от коалиция, или разчитаме на честна игра?
Илиян Гаврилов
18.03.2026 18:32

Няколко неща: 1. `elections_2026.get_results() # {"БСП": 1, "ГЕРБ-СДС": 5}` не трябва ли да е `elections_2026.get_results() # {"БСП": 1, "ГЕРБ-СДС": 10}`, тъй като на `GERB` предпочитаната валута е `gold_bars`? (1/0.2) * 2 = 10? 2. За коалицията пише, че "се инициализира с произволен брой PoliticalParty обекти", значи ли, че може с <2 партии? 3. `PPDB = DB + PP print(DB.members) # {"Да, България": ["Божо", "Ивайло Мирчев"], "ДСБ": ["Не-Иван-Костов", "Пак не е Иван Костов"], "ПП": ["Асенката"]}` не трябва ли да е `PPDB.members`, защото така се мутира `DB`, а в условието пише, че трябва да се създаде нова инстанция
Нишка
Виктор Бечев
18.03.2026 18:58

1. Прав си. 2. Според условието може. Не би следвало да има значение, въпреки че концептуално няма смисъл _(although, има някои коалиции, които се появяват "магически" като коалиции, нищо, че няма очевидни партии, които са се коалирали)_. 3. И за това си прав.
Милка Кръстева
18.03.2026 14:58

kebapcheta = Currency("кебапчета", 15) DPS = PoliticalParty("ДПС", kebapcheta) В описанието вторият позиционен аргумент не е опционален, а в примера тук липсва. :) Кое да приемем да вярно ?:) И опционалните параметри keyword ли са, или позиционни ? :) И отговора не трябва ли да е 6, защото kebapcheta са предпочитана валута на ДПС :)
Нишка
Виктор Бечев
18.03.2026 15:43

Права си, коригирахме. Що се отнася до опционалните параметри - `optional == keyword == default` параметър. Optional positional и другите езотерики няма да ви караме да ползвате.
Михаил Георгиев
18.03.2026 12:12

Може ли да попитам ако гласуваме за партия, която не е регистрирана дали трябва да има допълнителна проверка за това, също така методът get_results_by_year дали е static или class метод и откъде идват данните и coalition , мисля че се пише с едно L и дали това ще гръмне на тестовете и последно как се купуват гласове за коалиция дали трябва да изберем най-добрата партия демек тази, която дава най-много гласове
Нишка
Виктор Бечев
18.03.2026 12:28

1. Няма да тестваме гласуване с нерегистрирани партии. 2. Дали методът е статичен или класов ще решите вие. Ние дефинираме само интерфейса и поведението. 3. Данните за `get_results_by_year` са на базата на предходни инстанции на класът `Elections`. Т.е. ако имаме инстанции `Elections(2024)`, `Elections(2025)` и т.н. - функцията извикана за 2024 ще ни върне информация за изборите от тази година. 4. Абсолютно си прав за `Coalition` - оправяме го. И да, иначе ще гръмне, разбира се, защото няма да намери обект / клас с даденото име. 5. Гласовете се броят **на името на** коалиция, но за да купите възможно най-ефективно гласове - трябва да проверите дали случайно валутата не е `preferred_currency` за някоя от партиите в тази коалиция.
Михаил Георгиев
18.03.2026 12:36

Благодаря за уточненията и последно може ли да ползваме hasattr
Виктор Бечев
18.03.2026 15:32

Може, няма дерт.
Виктор Бечев
17.03.2026 22:48

Примерите са много, домашното не е сложно... Но е обемно, а ако все още не сте свикнали с ООП-то в [Python](https://www.youtube.com/watch?v=a1sn0ZSfnMo) - времеемко. Така че ви съветваме, да не го оставяте за последния момент. Оставаме насреща да ни питате ако има нещо неясно или пък сме допуснали грешка. Успех!
Нишка
Михаил Цанков
25.03.2026 00:02

закъснях с 1 мин ;0
Гергана Панделиева
25.03.2026 00:04

А позволи ли ти, изобщо да си качиш решението