Skip to content

Instantly share code, notes, and snippets.

@Gabrielcarvfer
Last active December 16, 2016 16:25
Show Gist options
  • Save Gabrielcarvfer/eb227a44b009d90c07f50b7fa69a483c to your computer and use it in GitHub Desktop.
Save Gabrielcarvfer/eb227a44b009d90c07f50b7fa69a483c to your computer and use it in GitHub Desktop.
Condorcet-like alternative voting algorithm
#CSV file in https://docs.google.com/spreadsheets/d/1tnMbbfBJH2fnNcn73t1oypcq8HrmFJZcdaek0CWapxY/edit?usp=sharing
import csv
import random
voters = []
#load csv into array of arrays
with open('Voto ordenado - Respostas ao formulário 1.csv', 'r') as csvfile:
lineReader = csv.DictReader(csvfile, delimiter=',')
for row in lineReader:
voters.append(dict(row));
#temporary data
roundsNum = 0
candidates = {
"" : [],
"Aécio Neves": [],
"Ciro Gomes": [],
"Eduardo Jorge": [],
"Geraldo Alckmin": [],
"Jair Bolsonaro": [],
"José Serra": [],
"Luciana Genro": [],
"Lula": [],
"Marina Silva": [],
"Robert Rey": [],
"Roberto Justus": [],
"Ronaldo Caiado": [],}
#list of excluded candidates
excludedCandidates = []
#clean blank votes
candidates.pop('')
excludedCandidates.append('')
for voter in voters:
blankPositions = []
for votes in voter:
if voter[votes] =='':
blankPositions.append(votes)
for position in blankPositions:
voter.pop(position)
#attach voter to candidate
for voter in voters:
# print (voter[list(voter.keys())[1]])
candidates[voter[list(voter.keys())[1]]].append(voter)
winner = []
majorityWinner = False
# rounds removing one candidate at a time
while len(candidates) > 1:
roundsNum += 1
minimalVotesNum = 99999999
minimalVoted = []
minimalVotedCandidates = {}
totalVotes = 0
#imprime votos cada candidate
print ("------------------Rodada " + str(roundsNum) + "-------------------------")
for candidate in candidates:
#calcula numero de votos de cada candidate
candidateVotes = len(candidates[candidate])
totalVotes += candidateVotes
#imprime numero de votos
print(candidate + " com " + str(candidateVotes) + " votos")
#procura candidates com menor numero de votos e os coloca numa lista
if candidateVotes < minimalVotesNum:
minimalVotesNum = candidateVotes
minimalVoted.clear()
minimalVoted.append(candidate)
else:
if (candidateVotes == minimalVotesNum):
minimalVoted.append(candidate)
#if you have dont have a draw with lower votes, find second lower
minimalVotesNum2 = 9999999
minimalVoted2 = []
if len(minimalVoted) < 2:
for candidate in candidates:
candidateVotes = len(candidates[candidate])
if (candidateVotes < minimalVotesNum2) and (candidateVotes > minimalVotesNum):
minimalVotesNum2 = candidateVotes
minimalVoted2.clear()
minimalVoted2.append(candidate)
#se a lista tiver algo, junte
if minimalVoted2:
minimalVoted.append(minimalVoted2[0])
print ("Total de votos da rodada: " + str(totalVotes))
for candidate in candidates:
if len(candidates[candidate]) >( (totalVotes/2)+1 ):
winner = candidate;
#print(candidate)
if winner:
majorityWinner = True;
break;
#apos contabilizar votos, seleciona aleatoriamente o pior candidate empatado
# para excluir (ideal é buscar recursivamente o melhor cenário para o pior candidate remanescente)
'''
#-----method 1: randomly select one of worst voted candidates----------
candidateIndex = random.randrange(0, len(minimalVoted))
#com o índice, acha a chave(nome) do candidato excluido para o round seguinte
candidateKey = minimalVoted[candidateIndex]
#---------------end of 1st method----------------------------
'''
'''
#-----method 2: worst cross candidate (less votes from other candidates with same num of votes)-----
if len(candidates[minimalVoted[0]]) > 0:
if (len(minimalVoted) > 1):
#create memory structure to hold votes
minimalVotedRank = {}
for candidate in minimalVoted:
minimalVotedRank[candidate] = 0
#check for crossed votes between worst candidates
for candidate in minimalVoted:
for voter in candidates[candidate]:
for vote in voter:
if voter[vote] in minimalVoted:
minimalVotedRank[voter[vote]]+=1
#discover who is the worst candidate
minVoteWorst = 99999999
rankVoteWorst = []
for rank in minimalVotedRank:
if (minimalVotedRank[rank] < minVoteWorst):
minVoteWorst = minimalVotedRank[rank]
rankVoteWorst = rank
#kill the bastard
candidateKey = rank
else:
candidateKey = minimalVoted[0]
else:
candidateIndex = random.randrange(0, len(minimalVoted))
candidateKey = minimalVoted[candidateIndex]
#---------------end of 2nd method----------------------------
'''
#-------method 3: condorcet-like----------------------------
# create memory structure to hold votes
for candidate in minimalVoted:
minimalVotedCandidates[candidate] = 0
# check for crossed votes between worst candidates
for candidate in candidates:
for voter in candidates[candidate]:
for vote in voter:
if voter[vote] in minimalVoted:
minimalVotedCandidates[voter[vote]] += 1
# discover who is the worst candidate
minVoteWorst = 99999999
rankVoteWorst = []
for rank in minimalVotedCandidates:
if (minimalVotedCandidates[rank] < minVoteWorst):
minVoteWorst = minimalVotedCandidates[rank]
rankVoteWorst = rank
# kill the bastard
candidateKey = rankVoteWorst
#---------------end of 3rd method----------------------------
#imprime o candidato excluido
#print ("Candidate " + candidateKey + " is out of the election")
minimalVoted.remove(rankVoteWorst)
print("Candidato " + candidateKey + " está fora da eleição (" + str(minimalVotedCandidates.pop(rankVoteWorst)) + " intenções de voto vs " + str(minimalVotedCandidates[minimalVoted[0]])+ " intenções de voto do(a) candidato(a) " + minimalVoted[0] +")")
#remove o candidato dos candidatos que ainda concorrem
excludedCandidate = candidates[candidateKey]
candidates.pop(candidateKey)
#guarda o nome do candidato para futura exclusão
excludedCandidates.append(candidateKey)
#redistribui votos do candidate excluido para suas segundas opções
if excludedCandidate:
for voter in excludedCandidate:
#remove candidato vencido
voter.pop(list(voter.keys())[1])
#verifica se o próximo candidato na preferência é válido
exit = False
while exit != True:
if len(list(voter.keys())) > 1:
nextCandidate = voter[list(voter.keys())[1]]
if nextCandidate not in excludedCandidates:
candidates[nextCandidate].append(voter)
exit = True
else:
voter.pop(list(voter.keys())[1])
else:
exit = True
print("----------------------------------------------------")
print("")
if majorityWinner == False:
print("E o vencedor é... " + list(candidates.keys())[0] + " com " + str(minimalVotedCandidates[list(candidates.keys())[0]]) + " votos")
else:
print("E o vencedor é... " + winner + ", com " + str(minimalVotesNum2) + " votos de "+ str(minimalVotesNum + minimalVotesNum2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment