Last active
December 18, 2015 11:50
-
-
Save tokland/e112ebaefbe65f0d638f to your computer and use it in GitHub Desktop.
Pure functional implementation of D'Hondt method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Pure functional implementation of D'Hondt method | |
from itertools import islice, count | |
from collections import Counter | |
from heapq import merge | |
def percentage(numerator, denominator): | |
return 100.0 * numerator / denominator | |
def take(n, it): | |
return islice(it, n) | |
def get_party_fractions(votes, name): | |
party_fractions = (float(votes) / n for n in count(1)) | |
return ((-fraction, name) for fraction in party_fractions) | |
def get_fractions(results): | |
sorted_results = sorted(((votes, name) for (name, votes) in results.items()), reverse=True) | |
return (get_party_fractions(votes, name) for (votes, name) in sorted_results) | |
def get_results_over_threshold(results, min_percentage): | |
total_votes = sum(results.values()) | |
return dict((name, votes) for (name, votes) in results.items() | |
if percentage(votes, total_votes) >= min_percentage) | |
def dhondt(results, total_seats, min_percentage=0): | |
""" | |
Return the seats distribution of results votes following the D'Hondt method. | |
>>> dhondt({"A": 10, "B": 8, "C": 3, "D": 2}, 8) | |
Counter({'A': 4, 'B': 3, 'C': 1}) | |
>>> dhondt({"A": 6, "B": 3, "C": 2}, 8, min_percentage=20) | |
Counter({'A': 6, 'B': 2}) | |
""" | |
results_over_threshold = get_results_over_threshold(results, min_percentage) | |
fractions = get_fractions(results_over_threshold) | |
assigned_party_names = (name for (fraction, name) in merge(*fractions)) | |
return Counter(take(total_seats, assigned_party_names)) | |
if __name__ == "__main__": | |
import doctest | |
doctest.testmod() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment