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.Antworten:
05AB1E ,
4239 BytesProbieren Sie es online!
In 05AB1E fehlt eine gute Rekursion, daher wäre die Implementierung einer binären Suche wie im Referenzcode schmerzhaft. Zum Glück müssen wir den Teiler gar nicht finden!
Nehmen wir ein einfaches Beispiel: [600, 379, 12, 9] Stimmen, 100 Sitze, keine Koalitionen, keine Bar. Zuerst berechnen wir, wie viele Fraktionssitze jede Partei erhält, wobei Fraktionssitze als definiert werden
party_votes * seats / sum_of_votes
. In unserem Beispiel ergibt dies [60, 37,9, 1,2, 0,9].Das Interessante daran ist, dass eine Partei, die nur einen
f
Bruchteil der Sitze erhält, entweder einenint(f)
oder einenint(f) + 1
echten Sitz erhält . Dies bedeutet, dass wir bereits wissen, wie 60 + 37 + 1 = 98 der Sitze zugewiesen werden, und dass wir 2 „Bonussitze“ zur Verteilung auf die 4 Parteien übrig haben (keine Partei kann mehr als 1 Bonussitz erhalten). An wen gehen diese Bonussitze? Die Parteien mit der höchsten Quote vonf / (int(f) + 1)
(Nachweis als Übung dem Leser überlassen). In unseren Beispielen sind die Verhältnisse so[0.98, 0.997, 0.6, 0.9]
, dass die ersten beiden Parteien jeweils einen Bonussitz erhalten.Werfen wir einen Blick auf den Code. Erstens ersetzen wir die Stimmenzahl aller Parteien, die die Messlatte nicht erreicht haben, durch 0:
Um die fehlende Rekursion zu umgehen
2F
, wiederholen wir den Hauptcode zweimal mit einem Pseudonym . Beim ersten Durchgang werden die gesamten Sitze zwischen den Koalitionen aufgeteilt, und beim zweiten Durchgang werden die Sitze jeder Koalition zwischen ihren Parteien aufgeteilt. Da der erste Durchgang nur einmal ausgeführt wird, der zweite Durchgang jedoch für jede Koalition ausgeführt wird, ist dies mit ziemlich viel Arbeit verbunden.Okay, nach diesem undurchsichtigen Teil ist die Spitze des Stapels nun eine Liste von Stimmen (Koalitionsstimmen im ersten Durchgang, Parteistimmen im zweiten Durchgang) und darunter die Anzahl der zuzuteilenden Sitze. Wir verwenden dies, um die Liste der Nachkommastellen zu berechnen:
Nun berechnen wir die Verhältnisse:
Bitweise klappt das nicht schön, hier. Es wird auf eine Ganzzahl gekürzt, 1 addiert und negiert, alles in einem einzigen Byte. Warum negieren? In 05AB1E gibt die Division durch 0 0 zurück, und diese müssen zuletzt sortiert werden.
D {# sortierte Kopie der Quoten ®1% # Bruchstimmen Mod 1 (auch als Dezimalzahl bezeichnet) O # Summe der oben genannten (dies ist die Anzahl der Bonussitze) ò # rund bis zum nächsten (erforderlich aufgrund von Gleitkomma bs) è # Index in die sortierten Verhältnisse
Dies ergibt das (n + 1) beste Verhältnis, wobei n die Anzahl der Bonusplätze ist (+1, da die Indexierung auf 0 basiert). Die Parteien, die einen Bonussitz erhalten, haben also ein Verhältnis, das strikt darunter liegt.
quelle
Python 2 , 220 Bytes
Probieren Sie es online!
Grundsätzlich nur ein Golf der Referenzimplementierung ...
quelle
Jelly ,
6336 BytesProbieren Sie es online!
Ein vollständiges Programm mit drei Argumenten: Anzahl der Stimmen in dem von der Frage beschriebenen Format, Takt und N in dieser Reihenfolge. Gibt eine Liste mit Sitzplatzzählern zurück. In der Fußzeile von TIO wird lediglich die Listenstruktur der Ausgabe hervorgehoben. (Andernfalls versteckt sich Jelly
[]
für Einzelpostenlisten.)Erläuterung
Ursprüngliche Einreichung (größer, aber effizienter)
Gelee , 63 Bytes
Probieren Sie es online!
quelle
Wolfram - kein Golf
War nur neugierig, es mit LinearProgramming zu lösen , kein Golfkandidat , aber vielleicht eine interessante Herangehensweise an ein Problem:
Lesen Sie eine Erklärung und probieren Sie es aus!
quelle