Вступ
На загальних виборах хочеться обчислити постійну ціну за місце в парламенті. Це означає, що для N >= 0
розподілу місць та списку ns
голосів на партію ми хотіли б знайти таку кількість d
, яка така
sum(floor(n/d) for n in ns) == N
Щоб зробити речі цікавими (і більше схожими на реальний світ), ми додамо ще два факти:
Дві партії можуть зібратися в "коаліцію", щоб місця були надані "коаліції" за сумою голосів за всі партії в ній. Тоді місця, отримані «коаліцією», поділяються між партіями аналогічним чином (знайти дільника тощо)
Партія, яка не пройшла певний відсоток голосів (наприклад, 3,25%), автоматично отримує 0 місць, і її голоси не враховуються за "коаліцію".
Виклик
Вам дано:
- Список списків, кожен із вкладених списків містить цілі числа (кількість голосів) і має довжину 1 для однієї партії або довжину 2 для "коаліції".
- Мінімальний відсоток голосів (він же "бар" за "загородження"), щоб отримати місця, як фракція (тому 3,25% дано як 0,0325)
- Загальна кількість місць для розподілу між усіма сторонами (ціле число)
Ви повинні надрукувати ту саму вкладену структуру списку, кількість голосів яких буде замінена місцями парламенту.
Winner - код з найменшою кількістю байтів.
Кутові корпуси:
- Можливо (і зазвичай буде) більше одного можливого дільника. Оскільки це не у виході, це насправді не має значення.
- Уявіть ,
N=10
іns = [[1]]
, таким чином , дільник може бути 0,1 (не є цілим числом) - У деяких випадках не може бути вирішена, наприклад
ns=[[30],[30],[100]]
,bar=0
,N=20
. Існує межа,d=7.5
де сума похилих значень стрибає з 19 до 21. Ви не плануєте вирішувати ці випадки. (дякую члену громади Арнольду, що вказав на цю справу)
Приклад введення та виводу
Дуже неоптимізований приклад Python3:
from math import floor
def main(_l, bar, N):
# sum all votes to calculate bar in votes
votes = sum(sum(_) for _ in _l)
# nullify all parties that didn't pass the bar
_l = [[__ if __ >= bar * votes else 0 for __ in _] for _ in _l]
# find divisor for all parliament seats
divisor = find_divisor([sum(_) for _ in _l], N)
# find divisor for each 'coalition'
divisors = [find_divisor(_, floor(sum(_)/divisor)) for _ in _l]
# return final results
return [[floor(___/_) for ___ in __] for _, __ in zip(divisors, _l)]
def find_divisor(_l, N, _min=0, _max=1):
s = sum(floor(_ / _max) for _ in _l)
if s == N:
return _max
elif s < N:
return find_divisor(_l, N, _min, (_max + _min) / 2)
else:
return find_divisor(_l, N, _max, _max * 2)
print(main(l, bar, N))
Приклад введення:
l = [[190970, 156473],
[138598, 173004],
[143666, 193442],
[1140370, 159468],
[258275, 249049],
[624, 819],
[1125881],
[152756],
[118031],
[74701]]
bar = 0.0325
N = 120
І його вихід:
[[6, 4], [0, 5], [4, 6], [35, 5], [8, 8], [0, 0], [35], [4], [0], [0]]
Ще кілька прикладів результатів:
Якщо bar=0.1
ми отримаємо цікаве протистояння між двома сторонами, оскільки жодна з менших партій не враховується:
[[0, 0], [0, 0], [0, 0], [60, 0], [0, 0], [0, 0], [60], [0], [0], [0]]
І якщо N=0
(кутовий випадок), то, звичайно, ніхто нічого не отримує:
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0], [0], [0], [0]]
d=7.5
ви отримуєте стрибок з 19 місць на 21 місце.