myr.quest

🎓 How Ranked Choice Voting Works

An instant runoff in a single ballot

Back to voting

The Problem with Normal Voting

In a normal election with 5 candidates, someone can win with just 21% of the vote. That means 79% of people didn't want the winner. This is called the spoiler effect - similar candidates split their supporters' votes.

Example: Pizza election

Pepperoni: 30%   Cheese: 25%   Margherita: 20%

Hawaiian: 15%   Veggie: 10%

Pepperoni "wins" but 70% wanted something else!

How RCV Fixes This

Instead of picking just one option, you rank all options from favorite to least favorite. Then the algorithm simulates multiple rounds of voting.

1

Count first choices

Everyone's #1 pick gets counted. If someone has more than 50%, they win immediately.

2

Eliminate the loser

The option with the fewest first-choice votes is eliminated.

3

Redistribute votes

Anyone whose #1 was eliminated now has their #2 pick count instead. Their vote isn't wasted!

4

Repeat

Keep eliminating and redistributing until someone crosses 50%.

Walkthrough: 10 Voters, 4 Options

Imagine 10 students voting on the next project:

Voter #1 #2 #3
4 votersSnake GameChat AppTodo App
3 votersChat AppSnake GameWeather
2 votersWeatherChat AppSnake Game
1 voterTodo AppChat AppSnake Game

Round 1 - Count first choices

Snake Game: 4  |  Chat App: 3  |  Weather: 2  |  Todo App: 1

Need 6 to win (>50% of 10). Nobody has it.

Todo App eliminated (1 vote, fewest).

Round 2 - Redistribute

That 1 Todo voter's #2 was Chat App, so Chat App gets +1.

Snake Game: 4  |  Chat App: 4  |  Weather: 2

Still need 6. Nobody has it.

Weather eliminated (2 votes, fewest).

Round 3 - Final redistribution

The 2 Weather voters' next active pick is Chat App.

Snake Game: 4  |  Chat App: 6

Chat App wins with 6/10 (60%)!

Notice: Snake Game had the most first-choice votes, but Chat App was the most broadly acceptable choice. That's the power of RCV.

The Algorithm (Pseudocode)

function ranked_choice_vote(ballots):
    active_candidates = all candidates

    while true:
        # Count first-choice votes
        counts = {}
        for ballot in ballots:
            first_active = first candidate in ballot
                           that is still active
            if first_active exists:
                counts[first_active] += 1

        total = sum of all counts
        threshold = floor(total / 2) + 1

        # Check for winner
        for candidate in counts:
            if counts[candidate] >= threshold:
                return candidate  # WINNER!

        # No winner - eliminate last place
        loser = candidate with min(counts)
        remove loser from active_candidates

        # Votes automatically redistribute
        # next loop iteration

Why RCV Matters

No spoiler effect

Voting for your true favorite never hurts you. If they lose, your vote transfers.

Majority winner

The winner always has more than 50% support (among remaining voters).

One ballot

No need for runoff elections. Everything happens in a single vote.

Real world use

Used in NYC, Alaska, Australia, Ireland, and many organizations worldwide.

💻 Coding Challenge

Try implementing RCV yourself! Here's the function signature in Python:

def run_rcv(candidates: dict[int, str],
            ballots: list[list[int]]) -> int | None:
    """
    candidates: {1: "Snake Game", 2: "Chat App", ...}
    ballots: [[2, 1, 3], [1, 3, 2], ...]
             each ballot is candidate IDs in preference order

    Returns: winning candidate ID, or None
    """
    pass  # Your code here!

Hint: You need a while loop, a way to count first-choice votes, and a way to eliminate the loser each round.