Вступление
На всеобщих выборах хотелось бы рассчитать постоянную цену за место в парламенте. Это означает, что для N >= 0распределения мест и списка nsголосов для каждой партии мы бы хотели найти число d,
sum(floor(n/d) for n in ns) == N
Чтобы сделать вещи интересными (и больше похожими на реальный мир), мы добавим еще два факта:
Две партии могут собираться в «коалицию», так что места в «коалиции» предоставляются суммой голосов за все партии в ней. Затем места, которые получила «коалиция», распределяются между партиями аналогичным образом (найдите делитель и т. Д.)
Партия, которая не набрала определенный процент голосов (например, 3,25%), автоматически получает 0 мест, и ее голоса не учитываются как «коалиция».
Вызов
Тебе дали :
- Список списков, каждый из вложенных списков содержит целые числа (количество голосов) и имеет длину 1 для одной партии или длину 2 для «коалиции».
- Минимальный процент голосов (он же «бар» за «заграждение»), чтобы получить места, в виде дроби (таким образом, 3,25% дается как 0,0325)
- Общее количество мест, которое будет распределено между всеми сторонами (целое число)
Вы должны распечатать ту же структуру вложенного списка, с количеством голосов, замененных местами в парламенте.
Победитель - это код с наименьшим количеством байтов.
Угловые чехлы:
- Там может (и обычно будет) более одного возможного делителя. Поскольку его нет в выводе, это не имеет значения.
- Представьте себе,
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 места.