Introducción
En una elección general, a uno le gustaría calcular un precio constante por escaño en el parlamento. Esto significa que para N >= 0que se distribuyan los escaños y una lista nsde votos por partido, nos gustaría encontrar un número dtal que
sum(floor(n/d) for n in ns) == N
Para hacer las cosas interesantes (y más como el mundo real), agregamos dos hechos más:
Dos partidos pueden reunirse en una 'coalición', de modo que los asientos se otorguen a la 'coalición' por la suma de los votos para todos los partidos en ella. Luego, los asientos que obtuvo la 'coalición' se dividen entre los partidos de manera similar (encontrar divisor, etc.)
Un partido que no aprobó cierto porcentaje de los votos (por ejemplo, 3.25%) automáticamente obtiene 0 escaños, y sus votos no cuentan para una 'coalición'.
Desafío
Te dan:
- Una lista de listas, cada una de las listas anidadas contiene números enteros (número de votos) y tiene una longitud de 1 para un solo partido, o una longitud de 2 para una 'coalición'.
- Porcentaje mínimo de votos (también conocido como "barra" para "bombardeo") para obtener escaños, como una fracción (por lo que 3.25% se da como 0.0325)
- Número total de asientos que se distribuirán entre todas las partes (entero)
Debe imprimir la misma estructura de lista anidada, con el número de votos sustituido por escaños en el parlamento.
El ganador es el código con la menor cantidad de bytes.
Casos de esquina:
- Puede haber (y generalmente habrá) más de un posible divisor. Como no está en la salida, realmente no importa.
- Imagina
N=10yns = [[1]], entonces el divisor puede ser 0.1 (no un entero) - Algunos casos no se pueden resolver, por ejemplo
ns=[[30],[30],[100]],bar=0,N=20. Hay un límited=7.5en el que la suma de los valores del piso salta de 19 a 21. No se espera que resuelva estos casos. (gracias al miembro de la comunidad Arnauld por señalar este caso)
Ejemplo de entrada y salida
Un ejemplo muy poco optimizado de 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))
Entrada de ejemplo:
l = [[190970, 156473],
[138598, 173004],
[143666, 193442],
[1140370, 159468],
[258275, 249049],
[624, 819],
[1125881],
[152756],
[118031],
[74701]]
bar = 0.0325
N = 120
Y su salida:
[[6, 4], [0, 5], [4, 6], [35, 5], [8, 8], [0, 0], [35], [4], [0], [0]]
Algunas salidas más de ejemplo:
Si bar=0.1obtenemos un enfrentamiento interesante entre dos partes, ya que ninguna de las partes más pequeñas se cuenta en:
[[0, 0], [0, 0], [0, 0], [60, 0], [0, 0], [0, 0], [60], [0], [0], [0]]
Y si N=0(caso de esquina), por supuesto, nadie obtiene nada:
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0], [0], [0], [0]]
d=7.5se obtiene un salto de 19 a 21 asientos.