# How Voting Systems Work 3, Exercise 1: a two-round runoff on a four-candidate club vote # 30 members rank four candidates (assumed, invented numbers). # Report round 1, whether anyone has a majority, and the runoff if needed. # Then check: does the runoff winner also win every head-to-head contest? from collections import Counter profile = ( [("Ana", "Bo", "Cy", "Di")] * 9 + [("Bo", "Cy", "Ana", "Di")] * 7 + [("Cy", "Bo", "Di", "Ana")] * 8 + [("Di", "Cy", "Bo", "Ana")] * 6 ) n = len(profile) first = Counter(b[0] for b in profile) print("round 1:", dict(sorted(first.items())), f"(majority needs more than {n / 2:g})") ranked = sorted(first, key=lambda c: (-first[c], c)) if first[ranked[0]] > n / 2: winner = ranked[0] print("outright winner:", winner) else: a, b = ranked[:2] a_votes = sum(1 for x in profile if x.index(a) < x.index(b)) print(f"no majority; runoff {a} vs {b}: {a_votes} to {n - a_votes}") winner = a if a_votes > n - a_votes else b print("runoff winner:", winner) beats_all = all( sum(1 for x in profile if x.index(winner) < x.index(y)) > n / 2 for y in profile[0] if y != winner ) print("beats every rival head to head:", beats_all) for y in sorted(profile[0]): if y != winner: w = sum(1 for x in profile if x.index(winner) < x.index(y)) print(f" {winner} vs {y}: {w} to {n - w}") # Output when run: # round 1: {'Ana': 9, 'Bo': 7, 'Cy': 8, 'Di': 6} (majority needs more than 15) # no majority; runoff Ana vs Cy: 9 to 21 # runoff winner: Cy # beats every rival head to head: False # Cy vs Ana: 21 to 9 # Cy vs Bo: 14 to 16 # Cy vs Di: 24 to 6