Einführung
Bei einer allgemeinen Wahl möchte man einen konstanten Preis pro Parlamentssitz berechnen. Dies bedeutet, dass wir für N >= 0
die Verteilung der Sitze und eine Liste ns
der Stimmen pro Partei eine d
solche Nummer finden möchten
sum(floor(n/d) for n in ns) == N
Um die Dinge interessanter (und realer) zu machen, fügen wir zwei weitere Fakten hinzu:
Zwei Parteien können sich zu einer "Koalition" zusammenschließen, so dass die Sitze der "Koalition" durch die Summe der Stimmen aller Parteien in ihr zugeteilt werden. Dann werden die Sitze der 'Koalition' in ähnlicher Weise zwischen den Parteien aufgeteilt (Teiler finden usw.)
Eine Partei, die einen bestimmten Prozentsatz der Stimmen nicht erreicht hat (z. B. 3,25%), erhält automatisch 0 Sitze, und ihre Stimmen zählen nicht für eine „Koalition“.
Herausforderung
Sie erhalten:
- Eine Liste von Listen, jede der verschachtelten Listen enthält ganze Zahlen (Anzahl der Stimmen) und hat die Länge 1 für eine einzelne Partei oder die Länge 2 für eine "Koalition".
- Minimaler Prozentsatz der Stimmen (alias "Balken" für "Sperrfeuer"), um Sitze zu erhalten, als Bruchteil (3,25% werden als 0,0325 angegeben)
- Gesamtzahl der auf alle Parteien zu verteilenden Sitze (Ganzzahl)
Sie müssen dieselbe verschachtelte Listenstruktur ausdrucken, wobei die Anzahl der Stimmen durch Parlamentssitze ersetzt wird.
Gewinner ist der Code mit der geringsten Anzahl von Bytes.
Ecke fällen:
- Es kann (und wird in der Regel auch) mehr als einen möglichen Teiler geben. Da es nicht in der Ausgabe enthalten ist, spielt es keine Rolle.
- Stellen Sie sich
N=10
und vorns = [[1]]
, der Divisor darf also 0,1 sein (keine ganze Zahl) - Einige Fälle können nicht gelöst werden, zum Beispiel
ns=[[30],[30],[100]]
,bar=0
,N=20
. Es gibt eine Grenze,d=7.5
an der die Summe der Floored-Werte von 19 auf 21 springt. Es wird nicht erwartet, dass Sie diese Fälle lösen. (Dank an Community-Mitglied Arnauld für den Hinweis auf diesen Fall)
Beispiel für Ein- und Ausgabe
Ein sehr nicht optimiertes Python3-Beispiel:
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))
Beispiel Eingabe:
l = [[190970, 156473],
[138598, 173004],
[143666, 193442],
[1140370, 159468],
[258275, 249049],
[624, 819],
[1125881],
[152756],
[118031],
[74701]]
bar = 0.0325
N = 120
Und seine Ausgabe:
[[6, 4], [0, 5], [4, 6], [35, 5], [8, 8], [0, 0], [35], [4], [0], [0]]
Einige weitere Beispielausgaben:
Wenn bar=0.1
wir eine interessante Auseinandersetzung zwischen zwei Parteien bekommen, da keine der kleineren Parteien dazugezählt wird:
[[0, 0], [0, 0], [0, 0], [60, 0], [0, 0], [0, 0], [60], [0], [0], [0]]
Und wenn N=0
(Eckfall) dann bekommt natürlich keiner was:
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0], [0], [0], [0]]
d=7.5
einen Sprung von 19 auf 21 Sitze bekommt.