Skip to content

Instantly share code, notes, and snippets.

@agam
Created December 19, 2013 02:19
Show Gist options
  • Select an option

  • Save agam/8033346 to your computer and use it in GitHub Desktop.

Select an option

Save agam/8033346 to your computer and use it in GitHub Desktop.
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <limits>
#include <string>
#include <vector>
using namespace std;
void GetVotes(
const vector<vector<int>>& votes,
int loser_index,
vector<int>* candidate_votes) {
// Use the round# to determine if votes should be transferred.
for (const vector<int>& vote : votes) {
int first_choice = vote[0];
int second_choice = vote[1];
if (loser_index >= 0) {
if (loser_index == first_choice) {
++((*candidate_votes)[second_choice]);
}
} else {
// first pass; just add the votes
++((*candidate_votes)[first_choice]);
}
}
if (loser_index >=0) { ((*candidate_votes)[loser_index]) = 0; }
}
bool CheckMajority(const vector<int>& candidate_votes, int total_votes, int* winner, int* loser) {
int max_votes = 0, min_votes = total_votes;
for (int i = 0; i < candidate_votes.size(); ++i) {
int v = candidate_votes[i];
if (max_votes < v) {
max_votes = v;
*winner = i;
}
if (min_votes > v) {
min_votes = v;
*loser = i;
}
}
if (max_votes * 2 > total_votes) {
return true;
} else {
return false;
}
}
void PrintStats(const vector<int>& candidate_votes, int total_votes, const vector<string>& candidate_names) {
for (int i = 0; i < candidate_votes.size(); ++i) {
if (candidate_votes[i] == 0) continue;
cout << fixed << setprecision(2) << (100.0 * candidate_votes[i])/total_votes << "% " << candidate_names[i];
if (i < candidate_votes.size() - 1) {
cout << ", ";
}
}
cout << endl;
}
int main() {
int num_votes, num_candidates;
cin >> num_votes >> num_candidates;
cout << "Will read in " << num_votes << " votes for " << num_candidates << " candidates." << endl;
vector<string> candidate_names;
vector<vector<int>> votes(num_votes, vector<int>(num_candidates));
for (int i = 0; i < num_candidates; ++i) {
string name;
cin >> name;
candidate_names.push_back(name);
}
for (int i = 0; i < num_votes; ++i) {
for (int j = 0; j < num_candidates; ++j) {
cin >> votes[i][j];
}
}
// Sanity check what we got.
cout << "Read in the following candidates :- \n";
for (const string& name : candidate_names) {
cout << name << endl;
}
cout << "Read in the following votes :- \n";
for (int i = 0; i < num_votes; ++i) {
for (int j = 0; j < num_candidates; ++j) {
cout << votes[i][j] << " ";
}
cout << endl;
}
vector<int> candidate_votes(num_candidates);
int round = 0, winner_index = -1, loser_index = -1;
do {
++round;
GetVotes(votes, loser_index, &candidate_votes);
cout << "Round " << round << ": ";
PrintStats(candidate_votes, num_votes, candidate_names);
} while (!CheckMajority(candidate_votes, num_votes, &winner_index, &loser_index) && round < 10);
cout << candidate_names[winner_index] << " is the winner.\n";
}
/*
Input Description
-----------------
On standard console input, you will be given two space-delimited integers, N and M. N is the number of votes, while M is the number of candidates. After this line, you will be given the candidates line, which is a space-delimited set of M-number of candidate names. These names are one-word lower-case letters only. This is followed by N-lines of ballots, where each ballot is a list of M-integers, from 0 to M-1, representing the order of preference.
Note that the order of preference for ballots goes from left-to-right. The integers are the index into the candidate list. For the example below, you can map 0: Knuth, 1: Turing, 2: Church. This means that if the ballot row is "1 0 2", that means the voter prefers Turing over Knuth over Church.
Output Description
------------------
Given the candidates and ballots, compute the first-round of successful candidates (e.g. rank them based on all ballot's first choice). If the percentage of votes for any one candidate is more than 50%, print the candidate name as the winner. Else, take all the votes of the least-successful candidate, and use their ballot's 2nd choice, summing again the total votes. If needed (e.g. there is no candidate that has more than 50% of the votes), repeat this process for the 3rd, 4th, etc. choice, and print the winner of the election.
For each round of computation, print the percentage of votes for each candidate, and rank them based on that percentage, using the output format.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment