Skip to content

Instantly share code, notes, and snippets.

@elderbas
Created November 13, 2020 01:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elderbas/3d32845fd5197c935236366f198d3e9f to your computer and use it in GitHub Desktop.
Save elderbas/3d32845fd5197c935236366f198d3e9f to your computer and use it in GitHub Desktop.
// 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