Introdução
Em uma eleição geral, alguém gostaria de calcular um preço constante por assento no parlamento. Isso significa que, para N >= 0
distribuir assentos e uma lista ns
de votos por partido, gostaríamos de encontrar um número d
tal que
sum(floor(n/d) for n in ns) == N
Para tornar as coisas interessantes (e mais parecidas com o mundo real), adicionamos mais dois fatos:
Dois partidos podem se reunir em uma 'coalizão', de modo que os assentos sejam dados à 'coalizão' pela soma dos votos para todos os partidos nela. Em seguida, os assentos que a 'coalizão' obteve são divididos entre os partidos de maneira semelhante (encontre divisor, etc.)
Um partido que não aprovou uma certa porcentagem dos votos (por exemplo, 3,25%) obtém automaticamente 0 assentos, e seus votos não contam para uma 'coalizão'.
Desafio
Você recebe:
- Uma lista de listas, cada uma das listas aninhadas, contém números inteiros (número de votos) e tem o comprimento 1 para um único partido ou o comprimento 2 para uma 'coalizão'.
- Porcentagem mínima de votos (também conhecida como "barra" para "barragem") para obter assentos, como uma fração (portanto, 3,25% é dado como 0,0325)
- Número total de assentos a serem distribuídos entre todas as partes (número inteiro)
Você deve imprimir a mesma estrutura de lista aninhada, com o número de votos substituído por cadeiras no parlamento.
Vencedor é o código com a menor quantidade de bytes.
Caixas de canto:
- Pode haver (e geralmente haverá) mais de um divisor possível. Como não está na saída, isso realmente não importa.
- Imagine
N=10
ens = [[1]]
, portanto, o divisor pode ser 0,1 (não um número inteiro) - Alguns casos não podem ser resolvidos, por exemplo
ns=[[30],[30],[100]]
,bar=0
,N=20
. Há um limite com od=7.5
qual a soma dos valores com base salta de 19 para 21. Não é esperado que você resolva esses casos. (obrigado ao membro da comunidade Arnauld por apontar este caso)
Exemplo de entrada e saída
Um exemplo muito otimizado do 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))
Exemplo de entrada:
l = [[190970, 156473],
[138598, 173004],
[143666, 193442],
[1140370, 159468],
[258275, 249049],
[624, 819],
[1125881],
[152756],
[118031],
[74701]]
bar = 0.0325
N = 120
E sua saída:
[[6, 4], [0, 5], [4, 6], [35, 5], [8, 8], [0, 0], [35], [4], [0], [0]]
Mais alguns exemplos de saídas:
Se bar=0.1
obtivermos um impasse interessante entre duas partes, uma vez que nenhuma das partes menores é contada:
[[0, 0], [0, 0], [0, 0], [60, 0], [0, 0], [0, 0], [60], [0], [0], [0]]
E se N=0
(canto), é claro que ninguém recebe nada:
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0], [0], [0], [0]]
d=7.5
você salta de 19 para 21 assentos.