introduction
Lors d'une élection générale, on souhaiterait calculer un prix constant par siège parlementaire. Cela signifie que pour la N >= 0
répartition des sièges et une liste ns
des votes par parti, nous aimerions trouver un nombre d
tel que
sum(floor(n/d) for n in ns) == N
Pour rendre les choses intéressantes (et plus comme le monde réel), nous ajoutons deux autres faits:
Deux partis peuvent se rassembler en une «coalition», de sorte que les sièges sont attribués à la «coalition» par la somme des voix de tous les partis. Ensuite, les sièges obtenus par la `` coalition '' sont répartis entre les partis de la même manière (trouver un diviseur, etc.)
Un parti qui n'a pas obtenu un certain pourcentage des voix (par exemple 3,25%) obtient automatiquement 0 siège, et ses votes ne comptent pas pour une «coalition».
Défi
On vous donne:
- Une liste de listes, chacune des listes imbriquées contient des nombres entiers (nombre de votes), et est de longueur 1 pour un parti unique, ou de longueur 2 pour une «coalition».
- Pourcentage minimal de votes (aka "bar" pour "barrage") pour obtenir des sièges, sous forme de fraction (donc 3,25% est donné comme 0,0325)
- Nombre total de sièges à répartir entre tous les partis (entier)
Vous devez imprimer la même structure de liste imbriquée, avec le nombre de votes substitué aux sièges du Parlement.
Winner est le code avec le plus petit nombre d'octets.
Cas d'angle:
- Il pourrait y avoir (et il y aura généralement) plus d'un diviseur possible. Comme il n'est pas dans la sortie, cela n'a pas vraiment d'importance.
- Imaginez
N=10
etns = [[1]]
, donc le diviseur peut être 0,1 (pas un entier) - Par exemple certains cas ne peuvent pas être résolus,
ns=[[30],[30],[100]]
,bar=0
,N=20
. Il y a une limite avecd=7.5
laquelle la somme des valeurs plancher passe de 19 à 21. On ne s'attend pas à ce que vous résolviez ces cas. (merci au membre de la communauté Arnauld d'avoir signalé ce cas)
Exemple d'entrée et de sortie
Un exemple Python3 très non optimisé:
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))
Exemple d'entrée:
l = [[190970, 156473],
[138598, 173004],
[143666, 193442],
[1140370, 159468],
[258275, 249049],
[624, 819],
[1125881],
[152756],
[118031],
[74701]]
bar = 0.0325
N = 120
Et sa sortie:
[[6, 4], [0, 5], [4, 6], [35, 5], [8, 8], [0, 0], [35], [4], [0], [0]]
Quelques autres exemples de sorties:
Si bar=0.1
nous obtenons une confrontation intéressante entre deux partis, car aucun des petits partis n'est compté dans:
[[0, 0], [0, 0], [0, 0], [60, 0], [0, 0], [0, 0], [60], [0], [0], [0]]
Et si N=0
(cas d'angle) alors bien sûr, personne ne reçoit rien:
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0], [0], [0], [0]]
d=7.5
vous obtenez un saut de 19 sièges à 21 sièges.