D’Hondt Method Calculator

D’Hondt Method is a mathematical method to calculate the number of seats for each party/list of people running for an election. It works by recursivelly applying a mathematical formula to the set of election results (the vote count). That formula is quite simple:

dhondt

Where V is the number of votes and s is the number of seats the party has so far.

Because it uses mathematical functions, control structures (loops) and lists, the D’Hondt method presents itself as a really good project for beginners in any programming language. In this example, I’ll be using Python (v3.5).

We need to start by initializing our variables. Looking at the formula above, we can see that we will need to know the number of seats available and the number of votes. Since each party will have a number of votes of its own, asking the users for the total ammount would be redundant. Instead, we’ll be asking for the number of parties running so that later on we can ask how many votes each party got (therefore, we we’ll need a list/array of parties). To get the data from the users we’ll be using the input function and casting its return value to an integer.

# How many parties and how many seats are there?
nSeats = int(input("How many seats are there?"))
nParties = int(input("How many parties are there?"))
# Array with the original values
parties = []
# Array that will be changed throughout the script
temp = []

Remember, in Python, anything after a # is considered a comment and will not be processed.

As you can see, in the first two commands we’re using the input function with a string as an argument which is what will appear to the user in the prompt. In the other commands we’re simply stating that parties and temp will be two empty arrays. The temp array will be used later for calculations.

Now that we know how many parties there are, we need to know how they are called and how many votes each one of those parties got. In other words, we need to populate the parties array.

# Get the needed data for each list
for i in range(1, nParties+1):
    append = 'th' if i > 3 else ('rd' if i == 3 else ('nd' if i == 2 else 'st'))
    name = input("Name of the "+str(i)+append+" party?")
    votes = int(input("Number of votes on party \""+name+"\"?"))
    parties.append({'name':name,'votes':votes})
    temp.append({'name':name,'votes':votes,'seats':0})

In the code above, you can see one of the most characteristic things in Python. Unlike most languages, it doesn’t use opening and closing statements (such as {} or endif) and you don’t need to declare the end of an expression. In Python good identation is essential as there is one expression per line and each line must be perfectly nested inside its scope.

Also in the code above, you’ll see two of the most essential control structures in any programming language: loops and if/else statements.

The for command runs the code nested inside its scope as long as the condition that is passed is true. In Python, the for loop is declared by defining a variable (that will have a different value on every loop) and a list (in this case, the numbers between 1 and the number of parties) through which it will run. Here, we could also have used any other type of loop, such as a while loop.

The first command inside the loop is nothing but a perfeccionism, but an important one for learning purposes. It will return the ordinal indicator for the current number (1 -> st, 2 -> nd, 3 -> rd, 4… -> th) It does so by using a special form of if/else statement called “ternary conditional operator” which is tipically used to save space while programming. I we were to get the ordinal indicator without using this kind of operator it would be something like:

if i == 1:
    append = 'st'
elif i == 2:
    append = 'nd'
elif i == 3:
    append = 'rd'
else:
    append = 'th'

Instead, we have:

append = 'th' if i > 3 else ('rd' if i == 3 else ('nd' if i == 2 else 'st'))

Which works by defining a value, setting the condition on which it is true and then defining what happens if the condition isn’t met. The example above nests three of those expressions in one single line.

To finish the loop, we ask the users for the number of votes the current party got, and save them on the arrays. Since Python is also an Object-Oriented language, we do that by calling the append method on the parties array and we pass it the content. In this case, every index of the parties array will be, in itself, an array with the same info for every party.

The temp array will have exactly the same information as the parties array plus info on how many seats the party already has.

And this is where the fun part begins. Now we have to determine how many seats each party gets.

# Begin loop to calculate seat distribution
for i in range(1, nSeats+1):
    # For each seat, find the party with more votes
    maxVotes = 0
    maxParty = 0
    partyIndex = 0
    twoOrMoreEqual = False;
    # For each party, find how many votes should be accounted for, when assigning the ith seat
    for j in temp:
        if (j['votes'] > maxVotes):
            # This is the party with the most votes, until now
            maxVotes = j['votes']
            maxParty = partyIndex
            twoOrMoreEqual = False
        elif (j['votes'] == maxVotes and maxVotes != 0):
            # The current party has the same ammount of votes has the one with more votes
            twoOrMoreEqual = True
        partyIndex += 1
    if (twoOrMoreEqual):
        # There are two or more parties with the same ammount of votes for this seat
        # Assign the seat to the party with the least total votes
        minVotes = 0
        minParty = 0
        n = 0
        for j in temp:
            if j['votes'] == maxVotes:
                if minVotes == 0: # first iteration, this is automatically the party with less votes
                    minVotes = parties[n]['votes']
                    minParty = n
                elif minVotes > parties[n]['votes']:
                    # This is the list with less votes until now
                    minVotes = parties[n]['votes']
                    minParty = n
            n+=1
        # A lista com menos votos totais e a que elege o mandato (o indice e igual)
        maxParty = minParty
        twoOrMoreEqual = False
    # Increment the number of seats taken by the party with more votes in this iteration
    temp[maxParty]['seats'] += 1
    # Finds the number of votes that will be taken into account for this party, in the nex iteration
    # by dividing th total ammount of votes it had, by the number of seats it has won +1
    temp[maxParty]['votes'] = parties[maxParty]['votes']/(temp[maxParty]['seats']+1)
    print(temp[maxParty]['name'] + ' - ' + str(maxVotes))

In the code above, a few things will be interesting for a beginner.

The first will be that we are declaring variables out of nowhere, which is perfectly valid in Python unlike, for instance, C or Java where you have to declare every variable and what type it has.

Second, loops inside loops, this is something quite common but that must be used carefully. Pay special attention not to use, in the loop declaration, a variable with the same name as the one you use in other loops in that scope. Loop-ception is particularly useful when you have multidimensional arrays like above, where we have several parties (1st dimension) and each party has several bits of information (2nd dimension).

Ans lastly, you can see how easy it is to access data inside a Python array. In the code above you can see it in different two ways. First when we loop through elements in the temp array.

for j in temp:
    if (j['votes'] > maxVotes):

Here, for every loop, j holds the information for that index. And you can access that information by calling the different indexes, in this case we want to get the votes for the current party.

And the second way used to get information from an array is by directly accessing an index:

temp[maxParty]['name']

Where we are getting the name of the party with most votes. Since maxParty holds the index of that party.

Now, for the algorithm used:

The D’Hondt method is used by comparing, for each party, the value that results from the application of the formula given at the begining of this article. For each seat, the party that has a bigger score, will get the seat. That being said, we must have a first loop that goes through all the seats available. Inside that loop, we must have another one that goes through all the parties, comparing the number of votes they got to the maximum so far. In the event of a tie, the winning party will be the one with less votes in total.

In the end of the first loop we change the values of the temp array for the winning party so that the number of seats is increased and the votes index holds the result from the application of the formula.

To finish, we print the results of the loop to the prompt and a summary in the end of the execution of the module:

print("============ TOTALS ============")
for j in temp:
	print(j['name'] + ' => ' + str(j['seats']))

You can download the code here: hondt.zip