So basically my program is supposed to make some sort of a runoff election( Here you can see what is it: https://cs50.harvard.edu/x/2020/psets/3/runoff/). I needed to implement 6 functions in order to do it and I did it. My program works perfectly fine but check50 says that function print_winner doesn't work ( though it only costs 4/24 possible points). This function must print the candidate of an election if he has a majority of all votes (>50%). The error says just "print_winner must print name when someone has a majority, print_winner did not print winner of election" and 3 more of such errors.
Here is the whole code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cs50.h>
#include <math.h>
#define MAX 9
typedef struct
{
string name;
int votes;
bool eliminated;
}
candidate;
candidate candidates[MAX];
int voter_count;
int candidate_count;
int preferences[MAX][MAX];
float winner_vote;
//void check_preference(void);
bool is_tie(int min);
bool vote(int voter, int rank, string name);
bool print_winner(void);
void tabulate(void);
int find_min(void);
void eliminate(int min);
int main(int argc, string argv[])
{
if (argc < 2)
{
printf("Usage: plurality [candidate ...]\n");
return 1;
}
candidate_count = argc - 1;
if (candidate_count > MAX)
{
printf("Maximum number of candidates is %i\n", MAX);
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: ");
winner_vote = voter_count / 2;
int integer = winner_vote;
if (winner_vote == integer)
{
winner_vote++;
}
else
{
winner_vote = ceil(winner_vote);
}
for (int i = 0; i < voter_count; i++)
{
for (int j = 0; j < candidate_count; j++)
{
string name = get_string("Rank %i ", j + 1);
if (!vote(i, j, name))
{
printf("Invalid vote\n");
j--;
}
}
printf("\n");
}
//check_preference();
while (true)
{
tabulate();
if (print_winner())
{
return 1;
}
else if (is_tie(find_min()))
{
return 1;
}
else
{
eliminate(find_min());
}
}
}
void eliminate(int min)
{
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].eliminated)
{
continue;
}
else if (min == candidates[i].votes)
{
candidates[i].eliminated = true;
}
}
}
int find_min(void)
{
int min = MAX;
for (int i = 1; i < candidate_count; i++)
{
if (candidates[i].eliminated)
{
continue;
}
else if (min > candidates[i].votes)
{
min = candidates[i].votes;
}
}
return min;
}
bool is_tie(int min)
{
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].eliminated)
{
continue;
}
else if (min == candidates[i].votes)
{
continue;
}
else
{
return 0;
}
}
return 1;
}
bool vote(int voter, int rank, string name)
{
bool exist = false;
for (int i = 0; i < candidate_count; i++)
{
if (strcmp(name, candidates[preferences[voter][i]].name) == 0 && rank > 0)
{
return 0;
}
if (strcmp(name, candidates[i].name) == 0)
{
preferences[voter][rank] = i;
exist = true;
break;
}
}
return exist;
}
bool print_winner(void)
{
// candidate candidateHolder;
for (int f = 0; f < candidate_count; f++)
{
//candidateHolder = candidates[f];
if (candidates[f].votes >= winner_vote)
{
printf("%s\n", candidates[f].name);
return 1;
}
}
return 0;
}
void tabulate(void)
{
int check = 0;
for (int i = 0; i < voter_count; i++)
{
if (!candidates[preferences[i][check]].eliminated)
{
candidates[preferences[i][check]].votes++;
check = 0;
}
else
{
check++;
i--;
}
}
}
Here is the function that creates error:
bool print_winner(void)
{
// candidate candidateHolder;
for (int f = 0; f < candidate_count; f++)
{
//candidateHolder = candidates[f];
if (candidates[f].votes >= winner_vote)
{
printf("%s\n", candidates[f].name);
return 1;
}
}
return 0;
}
looks like you forgot
"If any candidate has a majority (more than 50%) of the first preference votes, that candidate is declared the winner of the election."
The variables that are used to determine winner_vote (aka) the majority have to be floats i.e voter_count / 2. Integers will not work if you have to divide 3/2 or 5/2
Additionally, in order to win the majority, the candidates[f].votes has to be > the majority, not >=. In the latter instance a tie between two candidates would be printed in the print_winner function. Ties are determined in the is_tie function later in the code.
Bool functions must have a return value of true or false.
The problem here is that your printer_winner will return a 0 or a 1.
check50 expects a TRUE or FALSE.
a simple statement will fix that for you:
printf("%s", winner_vote ? "true" : "false");
This will convert the 1 and 0 to TRUE ans FALSE.
Hope this helps. First time programmer here ;).
I declared winner_vote in the function and it worked
The problem is it puts my function inside of their code. So winner_vote variable is undefined there. There's nothing to do with 1 or 0. By the way, 1 in a bool means true and 0 means false. Why I put them instead of words because the explanation video said return 1 if ... and return 0 if ... I thought maybe this will change something.
And my other problem was that i forgot to mark my answer as a correct one. So people are still trying to help
You could init two global variables one integer, other floating(int max;
float pmax;) and delete your unnecessary code and variables in the beginning.
Below your function content:
bool print_winner(void)
{
for (int i = 0; i < candidate_count; i++)
{
if (max < candidates[i].votes)
{
max = candidates[i].votes;
pmax = ((float) max /(float) voter_count);
if (pmax > 0.5)
{
printf("%s\n", candidates[i].name);
return true;
}
}
}
return false;
}
bool print_winner(void)
{
int maj = voter_count / 2;
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes > maj)
{
printf("%s\n",candidates[i].name);
return true;
}
}
return false;
}
Why don't you try this instead??
Why do you return an int when type specified is bool?
you can use this as an alternative as well
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;
}
// Print the winner of the election, if there is one
bool print_winner(void)
{
int won;
win_score = voter_count / 2;
won = win_score;
if (win_score == won)
{
win_score++;
}
else
{
win_score = ceil(win_score);
}
// for each candidate sum the 1st choices
// if candidates[i].votes > voters / 2; win then quit
// else call find_min then is_tie if so everyone wins else eliminate min
// then tabulate next rank to candidate/s
for (int j = 0; j < candidate_count; j++)
{
if (candidates[j].votes >= win_score)
{
printf("%s\n", candidates[j].name);
return 1;
}
}
return 0;
}
Related
This question already has answers here:
How do I properly compare strings in C?
(10 answers)
Closed 6 months ago.
This was part of the cs50 assignment.
Its a simple program which takes in the name of the candidate as vote and outputs the one which got called the highest time.
I tried running it, but it always outputs all the candidates as winners. When I looked into it the candidates[i].votes doesn't increment even though the code is present. I just wanna know why this is occurring.
#define MAX 9
void count(string name);
typedef struct
{
string name;
int votes;
}
candidate;
candidate candidates[MAX];
int candidate_count;
void print_winner(void);
int main(int argc, string argv[])
{
if (argc < 2)
{
printf("Usage: plurality [candidate ...]\n");
return 1;
}
candidate_count = argc - 1;
if (candidate_count > MAX)
{
printf("Maximum number of candidates is %i\n", MAX);
return 2;
}
for (int i = 0; i < candidate_count; i++)
{
candidates[i].name = argv[i + 1];
candidates[i].votes = 0;
}
int voter_count = get_int("Number of voters: ");
for (int i = 0; i < voter_count; i++)
{
string name = get_string("Vote: ");
count(name);
}
print_winner();
}
void count(string name)
{
for (int i = 0; i < candidate_count; i++)
{
if (name == candidates[i].name)
{
candidates[i].votes = candidates[i].votes + 1;
}
}
}
void print_winner(void)
{
int z = 0;
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes > z)
{
z = candidates[i].votes;
}
}
for (int i = 0; i < candidate_count; i++)
{
if (z == candidates[i].votes)
{
printf("the winner is %s\n",candidates[i].name);
}
}
}
Here's what i'd do when printing the winner
void print_winner(void)
{
int maxVotes = 0;
int winnerIndex = -1;
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes > maxVotes)
{
maxVotes = candidates[i].votes;
winnerIndex = i;
}
}
// for (int i = 0; i < candidate_count; i++)
// {
// if (z == candidates[i].votes)
// {
printf("the winner is %s\n",candidates[winnerIndex].name);
// }
// }
}
I have a C file that I am working on that is based on the run off system. however, I am running into some issues.
My tabulate function is able to tabulate the correct number of votes per candidate only when one candidate is eliminated per round, but unable to tabulate the correct votes per candidate when multiple people are eliminated or handle multiple preferences.
Here 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 (done and checked)
bool vote(int voter, int rank, string name)
{
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 (done)
void tabulate(void)
{
// TODO
for (int i = 0; i < candidate_count; i++)
{
for (int j = 0; j < voter_count; j++)
{
if (!candidates[i].eliminated)
{
if (preferences[j][0] == i)
{
candidates[i].votes++;
}
}
}
}
}
// Print the winner of the election, if there is one (done)
bool print_winner(void)
{
// TODO
for (int i = 0; i < candidate_count; i++)
{
float percent = ((float) candidates[i].votes / (float) voter_count);
if (percent > 0.5 && !candidates[i].eliminated)
{
printf("%s\n", candidates[i].name);
return true;
}
}
return false;
}
// Return the minimum number of votes any remaining candidate has (done)
int find_min(void)
{
// TODO
int min = 0;
for (int i = 0; i < candidate_count; i++)
{
if(!candidates[i].eliminated)
{
min = candidates[i].votes;
break;
}
}
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes < min && !candidates[i].eliminated)
{
min = candidates[i].votes;
}
}
return min;
}
// Return true if the election is tied between all candidates, false otherwise (done)
bool is_tie(int min)
{
// TODO
int count_votes = 0;
int count_false = 0;
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
count_false++;
}
}
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
count_votes = count_votes + candidates[i].votes;
}
}
double average = (double) count_votes / (double) count_false;
for(int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes == average && !candidates[i].eliminated)
{
return true;
}
}
return false;
}
// Eliminate the candidate (or candidates) in last place (done)
void eliminate(int min)
{
// TODO
int candidate_index;
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes == min)
{
candidate_index = i;
candidates[i].eliminated = true;
}
}
for (int i = 0; i < voter_count; i++)
{
if(preferences[i][0] == candidate_index)
{
for (int j = 1; j < candidate_count; j++)
{
preferences[i][j-1] = preferences[i][j];
}
}
}
for (int i = 0; i < voter_count; i++)
{
if(preferences[i][0] == candidate_index)
{
for (int j = 1; j < candidate_count; j++)
{
preferences[i][j-1] = preferences[i][j];
}
}
}
for (int i = 0; i < voter_count; i++)
{
if(preferences[i][0] == candidate_index)
{
for (int j = 1; j < candidate_count; j++)
{
preferences[i][j-1] = preferences[i][j];
}
}
}
for (int i = 0; i < voter_count; i++)
{
if(preferences[i][0] == candidate_index)
{
for (int j = 1; j < candidate_count; j++)
{
preferences[i][j-1] = preferences[i][j];
}
}
}
for (int i = 0; i < voter_count; i++)
{
if(preferences[i][0] == candidate_index)
{
for (int j = 1; j < candidate_count; j++)
{
preferences[i][j-1] = preferences[i][j];
}
}
}
for (int i = 0; i < voter_count; i++)
{
if(preferences[i][0] == candidate_index)
{
for (int j = 1; j < candidate_count; j++)
{
preferences[i][j-1] = preferences[i][j];
}
}
}
for (int i = 0; i < voter_count; i++)
{
if(preferences[i][0] == candidate_index)
{
for (int j = 1; j < candidate_count; j++)
{
preferences[i][j-1] = preferences[i][j];
}
}
}
for (int i = 0; i < voter_count; i++)
{
if(preferences[i][0] == candidate_index)
{
for (int j = 1; j < candidate_count; j++)
{
preferences[i][j-1] = preferences[i][j];
}
}
}
return;
}
The code should be able to handle multiple candidate elimination and multiple preferences as in eliminate(), I have coded it such that the first preference, preferences[voter_count][0] is always the most updated, and there would never have be votes of eliminated candidates as first preference. However, when i used the cs50 checker to check my work, it claims that my function cannot handle multiple eliminations and cannot handle multiple preferences.
After thinking and trying other methods, I came up with a loop in tabulate() to count the votes so that if the voter's first preference is eliminated, there would be another loop to find the voter's next candidate preference who was not eliminated. cs50 check threw back the same errors as it did previously, now adding that I cannot calculate the correct number of votes per person when only one person is eliminated.
The code is as such:
#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 (done and checked)
bool vote(int voter, int rank, string name)
{
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 (done)
void tabulate(void)
{
// TODO
for (int i = 0; i < candidate_count; i++)
{
for (int j = 0; j < voter_count; j++)
{
if (!candidates[i].eliminated)
{
if (preferences[j][0] == i)
{
candidates[i].votes++;
}
}
else
{
for (int k = 1; k < candidate_count; k++)
{
int e = preferences[j][k];
if (!candidates[e].eliminated)
{
candidates[e].votes++;
break;
}
}
}
}
}
}
// Print the winner of the election, if there is one (done)
bool print_winner(void)
{
// TODO
for (int i = 0; i < candidate_count; i++)
{
float percent = ((float) candidates[i].votes / (float) voter_count);
if (percent > 0.5 && !candidates[i].eliminated)
{
printf("%s\n", candidates[i].name);
return true;
}
}
return false;
}
// Return the minimum number of votes any remaining candidate has (done)
int find_min(void)
{
// TODO
int min = 0;
for (int i = 0; i < candidate_count; i++)
{
if(!candidates[i].eliminated)
{
min = candidates[i].votes;
break;
}
}
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes < min && !candidates[i].eliminated)
{
min = candidates[i].votes;
}
}
return min;
}
// Return true if the election is tied between all candidates, false otherwise (done)
bool is_tie(int min)
{
// TODO
int count_votes = 0;
int count_false = 0;
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
count_false++;
}
}
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
count_votes = count_votes + candidates[i].votes;
}
}
double average = (double) count_votes / (double) count_false;
for(int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes == average && !candidates[i].eliminated)
{
return true;
}
}
return false;
}
// Eliminate the candidate (or candidates) in last place (done)
void eliminate(int min)
{
// TODO
int candidate_index;
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes == min)
{
candidate_index = i;
candidates[i].eliminated = true;
}
}
return;
}
I have tested the code myself and still could not figure out why the amended code could not handle a single elimination, especially since I tested both codes with a simple use case whereas one candidate was eliminated, and it gave back the intended response.
Can someone see if I am doing something wrong, and give me pointer on how to get about this problem?
I also had the same problem...
I fix this by changing my tabulate function.
In my case, I forgot to concatenate the candidate variable inside the loop.
In the new solution, I generate a nested for. It works to me:
void tabulate(void)
{
int i = 0;
int j = 0;
for (i = 0; i < voter_count; i++)
{
for (j = 0; j < candidate_count; j++)
{
int id = preferences[i][j];
if (!candidates[id].eliminated)
{
candidates[id].votes++;
break;
}
}
}
}
I am trying to solve the runoff problem of pset3 in cs50. We have to find the result of a election when the voters input the choice of first 3 preference of candidates.If their isn't a winner with more than 50% of 1st preference of votes then the candidate with the least number of votes is eliminated and looped until there is a winner.
#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)
{
for (int k = 0; k < candidate_count; k++)
{
if (strcmp(name, candidates[k].name) == 0)
{
preferences[voter][rank] = k;
return true;
}
}
return false;
}
// Tabulate votes for non-eliminated candidates
void tabulate(void)
{
for (int i = 0; i < voter_count; i++)
{
for (int j = 0; j < candidate_count; j++)
{
if (!candidates[j].eliminated)
{
candidates.votes[preferences[i][j]]++;
break;
}
}
}
return;
}
// Print the winner of the election, if there is one
bool print_winner(void)
{
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
if (candidates.votes[i] > (voter_count * 0.5))
{
printf("%s", candidates.name[i]);
return true;
}
}
}
return false;
}
// Return the minimum number of votes any remaining candidate has
int find_min(void)
{
int k = candidates[1].votes;
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
if (k > candidates[i].votes)
{
k = candidates[i].votes;
}
}
}
return k;
}
// Return true if the election is tied between all candidates, false otherwise
bool is_tie(int min)
{
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
if (candidates[i].votes != min)
return false;
}
}
return true;
}
// Eliminate the candidate (or candidates) in last place
void eliminate(int min)
{
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
if (candidates[i].votes == min)
{
candidates[i].eliminated = true;
}
}
}
return;
}
When compiled it shows these errors
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow runoff.c -lcrypt -lcs50 -lm -o runoff
runoff.c:151:27: error: member reference base type 'candidate [9]' is not a structure or union
candidates.votes[preferences[i][j]]++;
~~~~~~~~~~^~~~~~
runoff.c:166:27: error: member reference base type 'candidate [9]' is not a structure or union
if (candidates.votes[i] > (voter_count * 0.5))
~~~~~~~~~~^~~~~~
runoff.c:168:40: error: member reference base type 'candidate [9]' is not a structure or union
printf("%s", candidates.name[i]);
I am not able to figure what's wrong.
In tabulate function, try changing this:
candidates.votes[preferences[i][j]]++;
to this:
candidates[preferences[i][j]].votes++;
In print_winner function, try changing this:
candidates.votes[i]
to this:
candidates[i].votes
and this:
printf("%s", candidates.name[i]);
to this:
printf("%s", candidates[i].name);
I'm having some problem with CS50's tideman in pset3.
Everything in check50 is correct except the very last one:
:( print_winner prints winner of election when some pairs are tied.
print_winner did not print winner of election
And here's my code:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// Max number of candidates
#define MAX 9
// preferences[i][j] is number of voters who prefer i over j
int preferences[MAX][MAX];
// locked[i][j] means i is locked in over j
bool locked[MAX][MAX];
// Each pair has a winner, loser
typedef struct
{
int winner;
int loser;
}
pair;
// Array of candidates
string candidates[MAX];
pair pairs[MAX * (MAX - 1) / 2];
int pair_count;
int candidate_count;
// Function prototypes
bool vote(int rank, string name, int ranks[]);
void record_preferences(int ranks[]);
void add_pairs(void);
void sort_pairs(void);
void lock_pairs(void);
void print_winner(void);
int main(int argc, string argv[])
{
// Check for invalid usage
if (argc < 2)
{
printf("Usage: tideman [candidate ...]\n");
return 1;
}
// Populate array of candidates
candidate_count = argc - 1;
if (candidate_count > MAX)
{
printf("Maximum number of candidates is %i\n", MAX);
return 2;
}
for (int i = 0; i < candidate_count; i++)
{
candidates[i] = argv[i + 1];
//printf("Candidate %i: %s\n", i + 1, argv[i + 1]);
}
// Clear graph of locked in pairs
for (int i = 0; i < candidate_count; i++)
{
for (int j = 0; j < candidate_count; j++)
{
locked[i][j] = false;
}
}
pair_count = 0;
int voter_count = get_int("Number of voters: ");
// Query for votes
for (int i = 0; i < voter_count; i++)
{
// ranks[i] is voter's ith preference
int ranks[candidate_count];
// Query for each rank
for (int j = 0; j < candidate_count; j++)
{
string name = get_string("Rank %i: ", j + 1);
if (!vote(j, name, ranks))
{
printf("Invalid vote.\n");
return 3;
}
}
record_preferences(ranks);
printf("\n");
}
add_pairs();
sort_pairs();
lock_pairs();
print_winner();
return 0;
}
// Update ranks given a new vote
bool vote(int rank, string name, int ranks[])
{
// TODO
for (int i = 0; i < candidate_count; i++)
{
if (strcmp(name, candidates[i]) == 0)
{
ranks[rank] = i;
return true;
}
}
return false;
}
// Update preferences given one voter's ranks
void record_preferences(int ranks[])
{
// TODO
int counter = 0;
for (int i = 0; i < candidate_count; i++)
{
int j = 1;
for (j += counter; j < candidate_count; j++)
{
preferences[ranks[i]][ranks[j]] += 1;
}
counter++;
}
return;
}
// Record pairs of candidates where one is preferred over the other
void add_pairs(void)
{
// TODO
int k = 0;
int l = 1;
for (int i = 0; i < candidate_count - 1; i++)
{
for (int j = l; j < candidate_count; j++)
{
if (preferences[i][l] > preferences[l][i])
{
pairs[k].winner = i;
pairs[k].loser = l;
pair_count++;
k++;
}
else if (preferences[i][l] < preferences[l][i])
{
pairs[k].loser = i;
pairs[k].winner = l;
pair_count++;
k++;
}
if (l < candidate_count - 1)
{
l++;
}
}
}
return;
}
// Sort pairs in decreasing order by strength of victory
//int strength [MAX];
pair temp[1];
void sort_pairs(void)
{
// TODO
for (int j = 0; j < candidate_count - 1; j++)
{
//if (strength[j] < strength[j + 1])
if (preferences[pairs[j].winner][pairs[j].loser] < preferences[pairs[j + 1].winner][pairs[j + 1].loser])
{
temp[0] = pairs[j + 1];
pairs[j + 1] = pairs[j];
pairs[j] = temp[0];
}
}
return;
}
// Lock pairs into the candidate graph in order, without creating cycles
pair first[1];
void lock_pairs(void)
{
// TODO
first[0] = pairs[0];
locked[pairs[0].winner][pairs[0].loser] = true;
for (int i = 1; i < candidate_count; i++)
{
if (pairs[i].loser == pairs[i - 1].winner)
{
first[0] = pairs[i];
}
locked[pairs[i].winner][pairs[i].loser] = true;
}
for (int j = 1; j < candidate_count; j++)
{
if (pairs[j].loser == first[0].winner)
{
locked[pairs[j].winner][pairs[j].loser] = false;
}
}
return;
}
// Print the winner of the election
void print_winner(void)
{
// TODO
printf("%s\n", candidates[first[0].winner]);
return;
}
As far as I know, if pairs are tied, they have the same strength? And does strength mean only the total preference on winner, or the difference between winner and loser? For example, if Charlie wins Alice 7-2, is the strength 5 or 7?
I don't quite understand what causes this error, any help please?
I trying to finish pset3 for CS50, plurality and my code does not update the votes for each candidate. I have implemented the vote function, but it seems not to work. Do you know where I need to improve my code?
This is my code at the moment:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// Max number of candidates
#define MAX 9
// Candidates have name and vote count
typedef struct
{
string name;
int votes;
}
candidate;
// Array of candidates
candidate candidates[MAX];
// Number of candidates
int candidate_count;
// Function prototypes
bool vote(string name);
void print_winner(void);
int main(int argc, string argv[])
{
// Check for invalid usage
if (argc < 2)
{
printf("Usage: plurality [candidate ...]\n");
return 1;
}
// Populate array of candidates
candidate_count = argc - 1;
if (candidate_count > MAX)
{
printf("Maximum number of candidates is %i\n", MAX);
return 2;
}
for (int i = 0; i < candidate_count; i++)
{
candidates[i].name = argv[i + 1];
candidates[i].votes = 0;
}
int voter_count = get_int("Number of voters: ");
// Loop over all voters
for (int i = 0; i < voter_count; i++)
{
string name = get_string("Vote: ");
// Check for invalid vote
if (!vote(name))
{
printf("Invalid vote.\n");
}
}
// Display winner of election
print_winner();
}
// Update vote totals given a new vote
bool vote(string name)
{
// TODO
for (int i = 0; i < candidate_count; i++)
{
if (strcmp(candidates[i].name, name) == 0)
{
candidates[i].votes++ ;
return true;
}
}
return false;
}
// Print the winner (or winners) of the election
void print_winner(void)
{
// TODO
int highest_vote = 0;
string winner;
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes >= candidates[0].votes)
{
highest_vote = candidates[i].votes;
winner = candidates[i].name;
}
}
printf("%s\n", winner);
return;
}
INPUT:
./plurality a b c d
Number of voters: 5
Vote: a
Vote: a
Vote: b
Vote: b
Vote: c
OUTPUT:
b
I have used debug50 to see where the problem lies, but I could not get to the solution. Has anyone also done pset3 and has any helpful ideas?
Your vote function seems to be fine. Print_winner, not so much. Some redundancy, some weird stuff. Try to keep it simple. I see you already solved it, but might help to compare where you used stuff/lines you didn't need.
void print_winner(void)
{
int winner = 0;
// The var 'winner' is an int, a number of votes, not a name.
// Finding the highest number of votes
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes > winner)
{
winner = candidates[i].votes;
}
}
// Printing the names of all candidates with 'winner' number of votes
for (int j = 0; j < candidate_count; j++)
{
if (candidates[j].votes == winner)
{
printf("%s\n", candidates[j].name);
}
}
return;
}
Your problem is here:
bool vote(string name)
{
// TODO
// LOOK OUT HERE FOR THE MISTAKE
for (int i = 0; i < candidate_count; i++)
{
if (strcmp(candidates[i].name, name) == 0)
{
candidates[i].votes++ ;
return true;
}
return false; // <<<<<<<<<<<<<<<<<< ERROR!
}
}
If you don't find a match during first iteration, you return from the function and bob never gets a change to count some votes.
You need to move the second return after the loop.
bool vote(string name)
{
for (int i = 0; i < candidate_count; i++)
{
if (strcmp(candidates[i].name, name) == 0)
{
candidates[i].votes++;
return true;
}
}
return false;
}
And another problem:
for (int i = 1; i <= candidate_count; i++)
{
if (candidates[i].votes > highest_vote)
{
candidates[i].votes = highest_vote;
}
}
First of all: The index should start at 0 as mentioned in my comment.
Second:
You must update highest_vote, not the other way around.
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes > highest_vote)
{
highest_vote = candidates[i].votes;
}
}