Reputation: 21
I'm stuck at the very beginning on the CS50 pset3 Runoff. Ive used several external resources but nothing is making sense. Please help me, this set has me about to quit because I do not understand.
Here are the instructions:
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)) // if vote bool is Not true
{
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 i = 0; i < candidate_count; i++)
{
if (strcmp (name, candidates[i].name) == 0)
{
preferences[voter][rank]++;
return true;
}
}
// TO DO
return false;
}
Upvotes: 2
Views: 5301
Reputation: 96
There is one mistake in your vote
function that you may have overlooked. If the voter's input is a valid candidate name, you want to put the candidates index in the preferences array, not just add on to that voters preference. Remember: the vote
function simply updates the voters ranked preferences, whereas the tabulate
function is where you actually tally up all the candidates votes.
Here's an example of what I mean. Imagine a runoff election with three candidates: Alice, Bob and Charlie. This means that the candidates array will store Alice in the zero index, Bob as the first index, and Charlie as the second index. Now imagine that the first voter has Bob as their preferred candidate, Charlie as their second preferred candidate, and Alice as their last choice. According to your function, your preferences[0]
will store an array with the elements {1, 1, 1}, because you are simply adding 1 to an empty preferences array every time that you say preferences[voter][rank]++;
. What you want to have in preferences[0]
is an array with the elements {1, 2, 0}. This is because the voter's first choice is Bob, aka candidates[1]
, their second choice is Charlie, aka candidates[2]
and their third choice is Alice, aka candidates[0]
.
So, by looping through the candidates list, you are getting the proper index of the candidate you want to add via the variable i
, so simply change your line of code to preferences[voter][rank] = i;
.
Your vote
function should look like this:
// Record preference if vote is valid
bool vote(int voter, int rank, string name)
{
for (int i = 0; i < candidate_count; i++)
{
if (strcmp(name, candidates[i].name) == 0)
{
preferences[voter][rank] = i;
return true;
}
}
return false;
}
PS: Stepping through debug50 is an excellent tool to use in these types of problems.
PPS: I hope you've already gotten past this problem but if not, I hope that you continue working through the course. The problem sets are challenging, but are worth it when you complete them.
Hi @user13569450 if this or any answer has solved your question please consider accepting it by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this.
Upvotes: 2