There’s more than one way to run an election!

There’s more than one way to run an election!

Prerequisites

  • function definition

  • list operations

Background

Continuing on in the theme of assignment 1, you will implement some Python functions related to different electoral systems. In particular, you will implement functions related to the first-past-the-post system (used to choose representatives in Parliament and Provincial legislatures) as well as ranked voting, used in Canada to decide some mayoral races as well as the leadership contests of many political parties.

Objective

To fully complete this assignment, you will implement five functions:

count_parties

counts the elements in a list

count_votes

counts the votes received by each party

first_choices

counts the first-choice votes for each party in a ranked voting system

remove

removes a less-preferred party from a list

ranked_ballot

performs a ranked-ballot election

Some of these functions will be fairly straightforward to implement; others may be more complex and take longer. Their specifications are described below in Details.

Suggestions

We are now reaching the point in the course where we can start to solve real and interesting problems such as this one. This problem is more complex than what we’ve faced before, so start now! You won’t want to leave this assignment for the last minute.

Another suggestion: don’t try to do it all at once! This problem is complex enough that you should solve it a bit at a time:

  1. Start by solving part of the problem (e.g., one of the first functions), working through just that part with our problem-solving workflow:

    1. Understand the problem (do it by hand a few times)

    2. Break it into smaller steps (write pseudocode or flowchart)

    3. Translate your solution into Python code

  2. Once you’ve solved part of the problem, expand your solution to handle larger and larger chunks of the problem (e.g., implementing multiple functions that work together). Follow the same workflow (understand/break/translate) each time you expand the problem until you have a solution to the whole assignment.

Remember that partial solutions will still earn partial credit. If you can only solve 3/4 of the assignment, you will still earn approximately 3/4 of the marks! It’s much better to earn 75% of the marks for a partial solution than to earn 0% by giving up (or by committing academic misconduct, e.g., letting a classmate tell you how to solve it).

Finally, if you’re not sure what to do, reach out. There are so many people here to help you, so please avail of our support! We won’t tell you the solution, but we will do something even better: ask you the right questions that help you find the solution.

Details

Here are the precise input/output specifications for the five functions I’ve asked you to write. They are described using docstrings, as we’ve talked about in class.

Counting parties

def count_parties(parties):
    """Count the number of parties in a list.

    Parameters
    ----------
    parties : list
        names of political parties

    Returns
    -------
    number of names in the list
    """

    pass

Counting votes

def count_votes(parties, votes):
    """Count the number of votes received by each party.

    This function will count the number of votes that each party in the list

    For example, if parties=['A', 'B', 'C'] and votes=['A', 'A', 'C', 'A', 'C'],
    this function should return [3, 0, 2].

    Parameters
    ----------
    parties : list of str
        political party names

    votes: list of str
        votes cast in an electoral district

    Returns
    -------
    list
        number of votes received by each party in the district, in the same
        order as in the `parties` parameter
    """

    pass

Ranked ballot choices

def first_choices(parties, ballots):
    """Determine how many first-choice votes each party received in a
    ranked-ballot system.

    In ranked-ballot voting, every voter has the opportunity to rank all
    candidates, rather than placing an X next to one candidate. This function
    examines a list of ballots and determines how many "first-choice" votes
    each party received.

    Parameters
    ----------
    parties : list
        a list of names of parties contesting an election

    ballots : list of lists
        a list of ballots, where each ballot is a list of party names in order
        of one voter's preference

    Returns
    -------
    list
        the number of first-choice votes each party received, in the same order
        as the list of parties
    """

    pass

Removing unpopular choices

def remove(needle, haystack):
    """Remove all instances of `needle` from the iterable `haystack`.

    This function will return a list that contains all of the values from
    `haystack` in the same order that they were presented, but without any
    instances of the value in `needle`.

    Parameters
    ----------
    needle
        value to remove all instances of from the haystack

    haystack : iterable
        iterable (e.g., list) of values

    Returns
    -------
    list
        a new list that contains all of the values from `haystack`
        *except* for the value in `needle`
    """

    pass

Ranked-ballot voting

def ranked_ballot(parties, ballots):
    """Determine who won an election based on ranked ballot.

    In ranked-ballot voting, every voter has the opportunity to rank all
    candidates, rather than placing an X next to one candidate. In the first
    round of voting, each voter's first choice is counted. If a candidate
    achieves 50% of the vote + 1, they win the election. Otherwise, the
    candidate with the lowest number of votes is dropped, changing who their
    first-choice voters are now voting for. For example, if a voter ranked
    party A, then C, then B, and party A is dropped from the ballot, the voter's
    ballot will now be C and then B.

    This process continues (voting and dropping the candidate/party with the
    lowest number of votes) until one candidate/party achieves 50% + 1.
    That candidate is then deemed elected.

    Parameters
    ----------
    parties : list
        a list of names of parties contesting an election

    ballots : list of lists
        a list of ballots, where each ballot is a list of party names in order
        of one voter's preference

    Returns
    -------
    str
        the name of the party/candidate who won the race
    """

    pass