Created
November 13, 2020 01:13
-
-
Save elderbas/3d32845fd5197c935236366f198d3e9f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// pre-process the lines of text into Array<Array<int>>; | |
const ballotsPreProcess = [ | |
[1, 2, 3], | |
[2, 1, 3], | |
[2, 3, 1], | |
[1, 2, 3], | |
[3, 1, 2], | |
]; | |
// also parse the lines of text into the respectiveCandidate names | |
const candidateAndVoting = { | |
names: [ | |
'John Doe', | |
'Jane Smith', | |
'Sirhan Sirhan' | |
], | |
// map the ballot vote 'candidate ID' to the | |
// candidate's corresponding index for easier mapping | |
ballots: ballotsPreProcess.map(listOfIDs => | |
listOfIDs.map(candidateID => candidateID - 1) | |
), | |
}; | |
getWinningCandidates() | |
function getWinningCandidates() { | |
const totalNumVotesPossible = candidateAndVoting.ballots.length; | |
const excludedCandidateIndices = new Set(); | |
while(true) { | |
/* | |
ex. | |
{ | |
1: [[1, 2, 3], [1, 3, 2]], | |
2: [[2, 1, 3], [2, 3, 1]], | |
3: [[3, 1, 2]], | |
} | |
*/ | |
const ballotsByCandidateIndex = _.groupBy(candidateAndVoting.ballots, (ballot) => { | |
return assignVoteToARemainingCandidateIndex(ballot, excludedCandidateIndices); | |
}); | |
// get the lowest possible count of a candidate(s) | |
const lowestBallotCountPossibleForACandidate = (function() { | |
const lowestPossibleCandidateBallotCount = Object.values(ballotsByCandidateIndex).map(v => v.length); | |
return Math.min(...lowestPossibleCandidateBallotCount); | |
})(); | |
let candidateIndicesWithLowestPossibleCount = []; | |
for (let candidateIndex in ballotsByCandidateIndex) { | |
console.log('ballotsByCandidateIndex', ballotsByCandidateIndex); | |
console.log('candidateIndex', candidateIndex); | |
const votesForCandidate = ballotsByCandidateIndex[candidateIndex].length; | |
if (votesForCandidate === lowestBallotCountPossibleForACandidate) { | |
candidateIndicesWithLowestPossibleCount.push(candidateIndex); | |
} | |
// let's just bounce out early if somebody has over 50% | |
if (votesForCandidate / totalNumVotesPossible > 0.5) { | |
return [candidateAndVoting.names[candidateIndex]]; | |
} | |
} | |
// if all are tied, they're all winners | |
const remainders = getRemainingCandidates(); | |
if (candidateIndicesWithLowestPossibleCount.length === remainders.length) { | |
return remainders; | |
} | |
// exclude all candidates that match this 'lowest' criteria, since it's not all of them | |
candidateIndicesWithLowestPossibleCount.forEach(candidateIndexToExclude => { | |
excludedCandidateIndices.add(candidateIndexToExclude); | |
}); | |
} | |
function assignVoteToARemainingCandidateIndex(orderedVote, excludedCandidateIndices) { | |
// get the first candidate from the left that IS NOT excluded | |
return _.find(orderedVote, (candidateIndex) => { | |
return !excludedCandidateIndices.has(candidateIndex.toString()); | |
}); | |
} | |
function getRemainingCandidates() { | |
return candidateAndVoting.names.filter((_name, index) => { | |
return !excludedCandidateIndices.has(index); | |
}) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment