Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Work out possible coalitions for the UK 2017 general election
"""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