Created
June 9, 2017 10:25
-
-
Save stuartlangridge/82295afd650cbafd8ab68202ef6f8c27 to your computer and use it in GitHub Desktop.
Work out possible coalitions for the UK 2017 general election
This file contains hidden or 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
"""2017 general election | |
Given the vote totals, we have a hung parliament. Work out how coalitions | |
might be put together and display possibilities. | |
""" | |
import itertools | |
# vote totals correct as of about 10.30am Friday 9th June 2017 | |
votes= { | |
'Conservative': 318, 'Sinn Fein': 7, 'DUP': 10, | |
'Sylvia Hermon': 1, 'Plaid Cymru': 4, 'Labour': 261, 'SNP': 35, | |
'Liberal Democrat': 12, 'Green Party': 1 | |
} | |
abbrs = { | |
'Conservative': 'CON', 'Sinn Fein': 'SF', 'DUP': 'DUP', | |
'Sylvia Hermon': 'Hermon', 'Plaid Cymru': 'PC', 'Labour': 'LAB', 'SNP': 'SNP', | |
'Liberal Democrat': 'LD', 'Green Party': 'Green' | |
} | |
items = votes.items() | |
combs = {} | |
winners = {} | |
# There are 650 MPs, so 326 is a majority. But Sinn Fein don't take their seats (7, as above) | |
# and the speaker and two deputy speakers don't really count, so a practical "if you have this | |
# many then you look like a viable coalition government" is 320. | |
WINTOTAL = 320 | |
for L in range(0, len(items)+1): | |
for subset in itertools.combinations(items, L): | |
parties = [x[0] for x in subset] | |
# OK, reject combinations that won't happen. First: don't display single parties in the list | |
if len(parties) == 1: continue | |
# There will be no Conservative + Labour coalition, obviously | |
if "Conservative" in parties and "Labour" in parties: continue | |
# The DUP explicitly said they don't like Labour | |
if "Democratic Unionist Party" in parties and "Labour" in parties: continue | |
# The LDs explicitly said they wouldn't go into coalitions with anyone | |
if "Liberal Democrat" in parties: continue | |
# Sinn Fein don't take their seats and will continue to not do so | |
if "Sinn Fein" in parties: continue | |
# No Green + CON: https://twitter.com/TheGreenParty/status/873023912430325765 | |
if "Conservative" in parties and "Green Party" in parties: continue | |
parties.sort(key=lambda p:(votes[p],p), reverse=True) | |
name = set([abbrs[x] for x in parties]) | |
namestr = ", ".join([abbrs[x] for x in parties]) | |
lnamestr = ", ".join(parties) | |
if len(lnamestr) < 40: namestr = lnamestr | |
total = sum([x[1] for x in subset]) | |
if total < 300: continue | |
combs[namestr] = total | |
if total >= WINTOTAL: | |
winners[namestr] = name | |
# Throw out all supersets; that is, if CON+DUP is enough to win, then obviously CON+DUP+PC | |
# is too, but don't count it; things on the winning list are the minimum possible. We don't | |
# throw out supersets of non-winning coalitions. | |
binit = set() | |
for ns, n in winners.items(): | |
for checkns, checkn in winners.items(): | |
if n < checkn: | |
binit.add(checkns) | |
for b in binit: | |
del combs[b] | |
ii = list(combs.items()) | |
ii.sort(key=lambda c: c[1], reverse=True) | |
banner = False | |
# and print the output graph. | |
print() | |
for n, v in ii: | |
vc = v // 20 | |
bar = "█" * vc | |
endbar = " " * (20 - vc) | |
if v < WINTOTAL and not banner: | |
print(" —————————— %s needed to look plausible? ——————————" % WINTOTAL) | |
banner = True | |
print (" %s%s%2d %s" % (bar, endbar, v, n)) | |
print() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment