#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)
{
for (int i = 0; i < candidate_count; i++)
{
if (strcmp(name, candidates[i].name) == 0)
{
candidates[i].votes ++;
return true;
}
}
return false;
}
// Print the winner (or winners) of the election printwinner(void)
void print_winner(void)
{
int temp = candidates[0].votes;
for (int i = 0; i < candidate_count; i++)
{
if (candidates[i].votes >= temp)
{
temp = candidates[i].votes;
}
}
for (int x = 0; x < candidate_count; x++)
{
if (temp == candidates[x].votes)
{
printf("Winner: %s\n", candidates[x].name);
}
}
}
Check50 says:
:( print_winner prints multiple winners in case of tie
Cause
print_winner function did not print both winners of election
:( print_winner prints all names when all candidates are tied
Cause
print_winner function did not print all three winners of election
My program prints multiple winners in case of a tie as well as in case of all candidates winning!
Related
This is the code I came up with for the print_winner function in the week 3 assignment of cs50, runoff.
this is my print_winner function.
Print_winner
It produces some strange behaviour. When the candidate obtains 100% of votes as rank 1, the code works fine. But any less than that the code just keeps on repeating infinitively. I have to use Ctr + c to stop the execution.
For example - ./runoff aa bb cc
if i give 100% of all the first ranks to "cc", it will print the winner correctly as "cc".
But if I give lets say if i give 2/3 of votes to cc and one vote for another, te codes keeps on looping.
This is my complete 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;
//debug
printf("candidate %d %s \n", i,candidates[i].name);
}
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");
}
//debug -vidu
for (int ss = 0; ss < voter_count; ss++)
{
for (int tt = 0; tt < 3; tt++)
{
printf("voter - %d, rank - %d, candidate no - %d \n" , ss, tt, preferences[ss][tt]);
}
}
// 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 //take all these details and enter them to the grid
int count = 0;
if (voter < voter_count && rank < 3)
{
for (int i = 0; i < candidate_count; i++)
{
//debug
printf("--name - %s,\n--candidate.name - %s \n", name, candidates[i].name);
if (strcmp(name, candidates[i].name) == 0)
{
preferences[voter][rank] = i;
//debug - print
printf("voter - %d, rank - %d, total votes - %d, %s \n", voter, rank, i, candidates[i].name);
count = count + 1;
return true;
break;
}
}
return false;
}
else
{
return false;
}
}
// Tabulate votes for non-eliminated candidates
void tabulate(void)
{
// TODO //take votes from preferences and put it to the candidates
for (int i = 0; i < voter_count; i++)
{
for (int j = 0; j < candidate_count; j++)
{
//check for the index no of preferences first candidate
if (preferences[i][0] == j && candidates[j].eliminated == false)
{
candidates[j].votes = candidates[j].votes + 1;
}
}
}
//debug = print the canditate table
for (int k = 0; k < candidate_count; k++)
{
printf("DEBUG in vote = Candid name - %s, Index no - %d, votes - %d \n",candidates[k].name, k,candidates[k].votes);
}
return;
}
// Print the winner of the election, if there is one
bool print_winner(void)
{
// TODO //If any candidate has more than half of the vote, their name should be printed and the function should return//if not false
//debug = print the canditate table
for (int k = 0; k < candidate_count; k++)
{
printf("DEBUG in print_winner = Candid name - %s, Index no - %d, votes - %d \n",candidates[k].name, k,candidates[k].votes);
}
int kk = 0;
//devide by total and
for (int j=0; j < candidate_count; j++)
{
kk = candidates[j].votes/voter_count * 100;
//debug
printf("candidate %d candidates[j].votes - %d \n", j, candidates[j].votes);
printf("candidate %d kk - %d \n", j, kk);
if (kk > 50)
{
printf("the winner is %s \n", candidates[j].name);
return true;
}
}
return false;
}
// Return the minimum number of votes any remaining candidate has
int find_min(void)
{
// TODO
//bubble sort
for (int step = 0; step < candidate_count; step++)
{
// loop to compare array elements
for (int i = 0; i < (candidate_count - 1); i++)
{
// compare two adjacent elements, change > to < to sort in descending order
if (candidates[i].votes > candidates[i + 1].votes)
{
// swapping occurs if elements are not in the intended order
candidate temp = candidates[i];
candidates[i] = candidates[i + 1];
candidates[i + 1] = temp;
}
}
}
return candidates[0].votes;
}
// Return true if the election is tied between all candidates, false otherwise
bool is_tie(int min)
{
// TODO
for (int i=0; i < candidate_count; i++)
{
if (candidates[i].votes == candidates[i + 1].votes && candidates[i].votes == min && candidates[i].votes == candidates[candidate_count].votes)
{
return true;
}
}
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].votes == min)
{
candidates[i].eliminated = true;
}
}
return;
}
There may be other issues, but one that jumps out is:
kk = candidates[j].votes/voter_count * 100;
Since both variables on the right hand side are of type int, the division is integer division. Since voter_count is always greater than or equal to candidates[j].votes, the value of kk is always either 0 or 100. To get floating point results, you could use:
kk = ((double)candidates[j].votes / (double)voter_count) * 100;
(Both casts aren't strictly necessary, and neither are the outer parens; that's a stylistic choice.)
I'm doing CS50 and I am currently at the Tideman problem. Here we have to write a function code that completes the vote function. When I do check my answers for the funtion it does work, although I don't completely understand how it does it.
I tried to debug it and see how the values change. Let me be clear it is about the vote funtion, and the part I don't understand is the INT vote. Why does it change value?
#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];
}
// 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 (hierin werken)
bool vote(int rank, string name, int ranks[])
{
printf("Rank begin snap niet %i \n", rank);
for (int i = 0; i < candidate_count; i++)
{
if (i == 3)
{
printf("0: %i 1: %i 2: %i", ranks[0], ranks[1], ranks[2]);
}
{
printf("Array rank %i \n", ranks[i]);
}
if (strcmp(candidates[i], name)==0)
{
ranks[rank] = i;
return true;
}
return false;
}
// Update preferences given one voter's ranks
void record_preferences(int ranks[])
{
// for (int i = 0; i < candidate_count; i++)
// if (ranks[i] < candidates[i])
// {
// int preferences[i][i] = ranks[i];
// }
// // TODO
return;
}
// Record pairs of candidates where one is preferred over the other
void add_pairs(void)
{
// TODO
return;
}
// Sort pairs in decreasing order by strength of victory
void sort_pairs(void)
{
// TODO
return;
}
// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs(void)
{
// TODO
return;
}
// Print the winner of the election
void print_winner(void)
{
// TODO
return;
}
o you understand how, if you have int array[10]; int j = 5; array[j] = 42;, then after the assignment, array[5] == 42? The same principles apply to ranks[rank] = i;. After the assignment, the element of the array ranks identified by rank contains the value in i at the time of the assignment. –
Jonathan Leffler
5 hours ago
Do you understand the array, j, and array[j] = 42 example? It is isomorphic with the ranks[rank] = i example. That is: array and ranks are both arrays of integers; j and rank are both indexes into the corresponding array; and 42 and i are the values assigned to the element of the array. The 'at the time of the assignment' qualifier is because if i changes after the assignment, the value in ranks[rank] doesn't change. –
Jonathan Leffler
5 hours ago
I have a problem when running this code. It is from the CS50. I am confused how the integers
rank and voter which are inputs for this bool vote(int voter, int rank, string name) get increased. I do not see any rank++ nor voters, yet somehow when the code is executed it works correctly and their value is increased, when the loop for getting the vote is executed. Thank you very much
#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;
}
bool vote(int voter, int rank, string name)
{
for(int i = 0; 0 < candidate_count; i++)
{
if(strcmp(candidates[i].name, name) == 0)
{
preferences[voter][rank]++;
return true;
}
}
// TODO
return false;
}
According to check50, the vote function does not return false when given a name of an invalid candidate. Furthermore, it modifies total votes when voting for an invalid candidate. I left the main function unchanged, according to instructions. Please help! What am I not seeing here?
Edit: added the rest of the code. When I run it with the example Alice and Bob as candidates and try to vote for Steve, instead of "Invalid vote" as the output should be, it gives me "Segmentation fault".
#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)
{
for (int i = 0; i < MAX; 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)
{
int high = 0;
for (int i = 0; i < MAX; i++)
{
if (candidates[i].votes > high)
{
high = candidates[i].votes;
}
}
for (int j = 0; j < MAX; j++)
{
if (candidates[j].votes == high)
{
printf("%s\n", candidates[j].name);
}
}
return;
}
In vote and print_winner you loop on entire candidates array.
for (int i = 0; i < MAX; i++)
What do you think can happen when you fill only 2 candidates and try to access 3rd item of array which has not been initialized ? Usually, undefined behavior.
I am working on cs50 plurality problem. When I try to vote for a candidate that wasn't in my argv I expected "Invalid vote.\n" to be printed however my program ends in Sementation fault. Could anyone explain why? I think my logic for my bool vote may be flawed but I am not sure. Thank you!
#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)
{
for (int i = 0; i < MAX; i++)
{
if (strcmp(candidates[i].name, name) == 0)
{
return true;
}
}
return false;
}
// Print the winner (or winners) of the election
void print_winner(void)
{
// TODO
return;
}
.......................................
.......................................
.......................................
...................................
In function vote() the loop
for (int i = 0; i < MAX; i++)
is checking every record's string, including those with a NULL pointer.
You should use candidate_count the number of elements set.
for (int i = 0; i < candidate_count; i++)
It only goes wrong when a match for a name is not found, because the loop index only then exceeds the number of names recorded.