Skip to content

Instantly share code, notes, and snippets.

@Srekel
Last active January 12, 2019 13:27
Show Gist options
  • Select an option

  • Save Srekel/7832f4d280978218dc383afcd16120ef to your computer and use it in GitHub Desktop.

Select an option

Save Srekel/7832f4d280978218dc383afcd16120ef to your computer and use it in GitHub Desktop.
Wild predictions for the Swedish election of 2018
import itertools
import os
import operator
import colorama
from colorama import Fore, Back, Style
colorama.init()
#os.system("cls")
class Party:
def __init__(self, name, likes, votes, style):
self.name = name
self.likes = likes
self.votes = votes
self.style = style
def __repr__(self):
return Style.BRIGHT + self.style + self.name.upper() + Style.RESET_ALL
def nonstyled_str(self):
return self.name.upper()
class Combination:
def __init__(self, parties, like_value, chance_of_50):
self.parties = sorted(parties, key=operator.attrgetter('votes'))
self.parties.reverse()
self.like_value = like_value
self.chance_of_50 = chance_of_50
def chance(self):
return self.like_value * self.chance_of_50
def total_votes(self):
return sum([p.votes for p in self.parties])
def __lt__(self, other):
return self.chance() < other.chance()
#return self.total_votes() < other.total_votes()
def __repr__(self):
partylist = ", ".join([str(p) for p in self.parties])
partylist_nonstyled = ", ".join([p.nonstyled_str() for p in self.parties])
partylist_padding = " " * (20 - len(partylist_nonstyled))
score = 100 * self.chance()
total_votes_str = "%10.1f" % self.total_votes()
if self.total_votes() > 45:
total_votes_str = Style.BRIGHT + getattr(Fore, "YELLOW") + total_votes_str + Style.RESET_ALL
return "%s %s %8.0f %s %%" % (partylist, partylist_padding, score, total_votes_str)
parties = []
pv = Party( "v", {"s": 1, "c": 0.6, "l": 0.3, "mp": 1}, 7.9, getattr(Fore, "RED"))
ps = Party( "s", {"kd": 0.1, "m": 0.2, "v": 0.7, "mp": 1, "l": 0.4, "c": 0.5}, 28.4, getattr(Fore, "RED"))
pmp = Party("mp", {"m": 0.3, "v": 0.5, "s": 1, "c": 0.6, "l": 0.5}, 4.3, getattr(Fore, "GREEN"))
psd = Party("sd", {"kd": 1, "m": 1, "l": 0.5, "c": 0.5, "s": 0.2}, 17.6, getattr(Fore, "YELLOW"))
pc = Party( "c", {"kd": 0.7, "m": 1, "l": 1, "s": 0.6, "mp": 0.5}, 8.6, getattr(Fore, "MAGENTA"))
pm = Party( "m", {"kd": 1, "c": 1, "l": 1, "s": 0.2, "sd": 0.6, "mp": 0.7}, 19.8, getattr(Fore, "BLUE"))
pl = Party( "l", {"kd": 0.5, "c": 1, "m": 1, "s": 0.6, "mp": 0.7}, 5.5, getattr(Fore, "MAGENTA"))
pkd = Party("kd", {"sd": 0.8, "c": 1, "m": 1, "l": 1, "s": 0.5, "mp": 0.8}, 6.4, getattr(Fore, "BLUE"))
parties.append(psd)
parties.append(pv)
parties.append(ps)
parties.append(pmp)
parties.append(pkd)
parties.append(pc)
parties.append(pm)
parties.append(pl)
for p1 in parties:
for p2 in parties:
if p1 != p2:
if not p2.name in p1.likes:
p1.likes[p2.name] = 0.001
print(p1.name , p2.name)
combinations = []
for comb_size in range(3, len(parties)+1):
for ps in itertools.combinations(parties, comb_size):
like_value = 1
for p1 in ps:
for p2 in ps:
if p1 == p2:
continue
mutual_like = min(p1.likes[p2.name], p2.likes[p1.name])
like_value *= mutual_like
total_votes = sum([p.votes for p in ps])
chance_of_50 = total_votes - 30
print(ps, like_value, total_votes, chance_of_50)
if like_value < 0.00000001:
continue
if chance_of_50 < 10:
continue
combo = Combination(ps, like_value, chance_of_50)
combinations.append(combo)
combinations.sort()
combinations.reverse()
print("")
print("PARTIES SCORE TOTAL_VOTES" )
print("--------------------|------------|--------------")
for c in combinations[:15]:
print(c)
print("")
@Srekel
Copy link
Author

Srekel commented Sep 9, 2018

With pre-election poll numbers, here's the output:


PARTIES                  SCORE      TOTAL_VOTES
-----------------------|----------|-------------
S, C, M                 28.67       51.2 %
S, M, L                 23.30       49.1 %
S, MP, M                19.46       47.6 %
S, C, M, L               7.25       57.7 %
S, KD, M                 5.31       48.3 %
S, MP, C, M              3.25       56.2 %
S, MP, M, L              2.08       54.1 %
SD, KD, M, L             2.07       49.0 %
S, KD, C, M              1.11       56.9 %
S, KD, M, L              0.55       54.8 %
V, S, M                  0.50       52.6 %
SD, C, M                 0.34       45.4 %
SD, KD, C, M             0.28       51.1 %
S, MP, C, M, L           0.26       62.7 %
SD, S, M                 0.22       61.7 %

@Srekel
Copy link
Author

Srekel commented Sep 10, 2018

Day-after-election votes (plus tweaks to numbers/algo)


PARTIES                  SCORE      TOTAL_VOTES
--------------------|------------|--------------
V, S, MP               678.40       40.6 %
C, M, L                390.00       33.9 %
KD, C, M               235.20       34.8 %
KD, C, M, L            181.69       40.3 %
SD, KD, M              141.31       43.8 %
S, MP, C               101.70       41.3 %
KD, M, L                61.20       31.7 %
S, C, M                 60.30       56.8 %
S, C, L                 50.00       42.5 %
S, M, L                 34.13       53.7 %
S, MP, L                32.80       38.2 %
S, MP, M                18.22       52.5 %
S, C, M, L              11.63       62.3 %
MP, C, M                 8.75       32.7 %
MP, C, M, L              6.64       38.2 %
S, MP, C, L              6.05       46.8 %
S, KD, C                 1.64       43.4 %

@Srekel
Copy link
Author

Srekel commented Jan 12, 2019

After tweaking a few numbers and fixing some output prettyfication, here are the results:

image

(Yellow means >45% )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment