The code I write has to run a runoff election. I have finished all of the code already that I have to do. However, I get an issue in the tabulate
function. I passed all the checks when I ran it through check50 for all my code except a specific error in the tabulate
function.
Some questions I got asked for a reproducible example. I found an example someone used for code and it produces the error in my code as well. I inputted 4 candidates (a,b,c,d) and 5 voters with their preferences ranked. The winner of this election should be candidate b. However, my code outputs candidates a, b, and d as the winners.
Voter 1: d,c,b,a
Voter 2: a,b,c,d
Voter 3: a,b,c,d
Voter 4: b,c,a,d
Voter 5: b,c,a,d
The specific error I am getting is -
:( tabulate handles multiple rounds of preferences tabulate did not produce correct vote totals
I've looked through multiple solutions people have had on here but couldn't find anything related to the code I wrote.
This is my code
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// Max voters and candidates
#define MAX_VOTERS 100
#define MAX_CANDIDATES 9
// preferences[i][j] is jth preference for voter i
int preferences[MAX_VOTERS][MAX_CANDIDATES];
// Candidates have name, vote count, eliminated status
typedef struct
{
string name;
int votes;
bool eliminated;
}
candidate;
// Array of candidates
candidate candidates[MAX_CANDIDATES];
// Numbers of voters and candidates
int voter_count;
int candidate_count;
// Function prototypes
bool vote(int voter, int rank, string name);
void tabulate(void);
bool print_winner(void);
int find_min(void);
bool is_tie(int min);
void eliminate(int min);
int main(int argc, string argv[])
{
// Check for invalid usage
if (argc < 2)
{
printf("Usage: runoff [candidate ...]\n");
return 1;
}
// Populate array of candidates
candidate_count = argc - 1;
if (candidate_count > MAX_CANDIDATES)
{
printf("Maximum number of candidates is %i\n", MAX_CANDIDATES);
return 2;
}
for (int i = 0; i < candidate_count; i++)
{
candidates[i].name = argv[i + 1];
candidates[i].votes = 0;
candidates[i].eliminated = false;
}
voter_count = get_int("Number of voters: ");
if (voter_count > MAX_VOTERS)
{
printf("Maximum number of voters is %i\n", MAX_VOTERS);
return 3;
}
// Keep querying for votes
for (int i = 0; i < voter_count; i++)
{
// Query for each rank
for (int j = 0; j < candidate_count; j++)
{
string name = get_string("Rank %i: ", j + 1);
// Record vote, unless it's invalid
if (!vote(i, j, name))
{
printf("Invalid vote.\n");
return 4;
}
}
printf("\n");
}
// Keep holding runoffs until winner exists
while (true)
{
// Calculate votes given remaining candidates
tabulate();
// Check if election has been won
bool won = print_winner();
if (won)
{
break;
}
// Eliminate last-place candidates
int min = find_min();
bool tie = is_tie(min);
// If tie, everyone wins
if (tie)
{
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
printf("%s\n", candidates[i].name);
}
}
break;
}
// Eliminate anyone with minimum number of votes
eliminate(min);
// Reset vote counts back to zero
for (int i = 0; i < candidate_count; i++)
{
candidates[i].votes = 0;
}
}
return 0;
}
// Record preference if vote is valid
bool vote(int voter, int rank, string name)
{
// TODO
//loop over all candidates, and within each voter saves their preferences for each candidate
for (int i = 0; i < candidate_count; i++)
{
if (strcmp(candidates[i].name, name) == 0)
{
preferences[voter][rank] = i;
return true;
}
}
return false;
}
// Tabulate votes for non-eliminated candidates
void tabulate(void)
{
// TODO
//loop over all voters
for (int i = 0; i < voter_count; i++)
{
//check voter(i's) 1st preference(0th index), if voter(i) 1st preference isn't eliminated, update vote for candidate 1(0th index)
//if voter(i) 1st preference is eliminated, check voter(i) 2nd preference
//if 2nd preference isn't eliminated, update vote for candidate corresponding to 2nd candidate, voter[i][j+1]
for (int j = 0; j < candidate_count; j++)
{
if (candidates[preferences[i][j]].eliminated == false)
{
candidates[preferences[i][j]].votes++;
}
else if(candidates[preferences[i][j]].eliminated == true)
{
candidates[preferences[i][j+1]].votes++;
}
break;
}
}
return;
}
// Print the winner of the election, if there is one
bool print_winner(void)
{
// TODO
//define variable highest_vote to zero
int majority_vote = voter_count/2;
//loop over every candidate, if their vote count is higher than highest_vote, set highest_vote equal to the highest candidates vote count
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes > majority_vote)
{
printf("%s\n", candidates[i].name);
return true;
}
}
return false;
}
// Return the minimum number of votes any remaining candidate has
int find_min(void)
{
// TODO
int min_votes = voter_count;
//loop through all candidates to find lowest vote count
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].eliminated == false && candidates[i].votes < min_votes)
{
min_votes = candidates[i].votes;
}
}
return min_votes;
}
// Return true if the election is tied between all candidates, false otherwise
bool is_tie(int min)
{
// TODO
bool tie_check = false;
//loop through all candidates, if candidates are tied, variable will be true
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].eliminated == false && candidates[i].votes == min)
{
tie_check = true;
}
else if (candidates[i].eliminated == false && candidates[i].votes != min)
{
tie_check = false;
}
}
if (tie_check == true)
{
return true;
}
else
{
return false;
}
}
// Eliminate the candidate (or candidates) in last place
void eliminate(int min)
{
// TODO
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].eliminated == false && min == candidates[i].votes)
{
candidates[i].eliminated = true;
}
}
return;
}
I just found out what was wrong with my code. It lied in
else if (candidates[preferences[i][j]].eliminated == true)
{
candidates[preferences[i][j + 1]].votes++;
}
break;
This was causing my code to incorrectly update the vote count for the candidates. My thought process for writing this code was if the candidate for that rank was eliminated, then add a vote to the next preference or rank which was the candidates[preferences[i][j+1]].votes++;
line. This caused a misalignment in my votes count so here is my solution. It was also unnecessary because I could have just added a break;
into the if statement.
I deleted the entire code that was wrong above. Then I simply added a break;
into the if statement. The correct tabulate function now looks like this as a completed version.
// Tabulate votes for non-eliminated candidates
void tabulate(void)
{
//loop over all voters
for (int i = 0; i < voter_count; i++)
{
//loop over all candidates
//check voter(i's) 1st preference(0th index), if voter(i) 1st preference isn't eliminated, update vote for candidate 1(0th index)
//break out of the loop so you don't update votes for all preferences for each voter
for (int j = 0; j < candidate_count; j++)
{
if (candidates[preferences[i][j]].eliminated == false)
{
candidates[preferences[i][j]].votes++;
break;
}
}
}
return;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.