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.)
Related
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
#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!
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 currently working on CS50's pset3 called Tideman. I am new to coding and I would love some input of someone who has some more experience.
One of the tasks for the student is to sort the pairs created during the tideman method of voting. My question continues below my current code, the part that matters is void sort_pairs(void) and I have added numbers to the left side so that it pops out.
#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
bool vote(int rank, string name, int ranks[])
{
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[])
{
for (int i = 0; i < candidate_count; i++)
{
for (int j = i + 1; j < candidate_count; j++)
{
preferences[ranks[i]][ranks[j]]++;
}
}
return;
}
// Record pairs of candidates where one is preferred over the other
void add_pairs(void)
{
for (int i = 0; i < candidate_count; i++)
{
for (int j = i + 1; j < candidate_count; j++)
{
if (preferences[i][j] > preferences[j][i])
{
pairs[pair_count].winner = i;
pairs[pair_count].loser = j;
pair_count++;
}
else if (preferences[i][j] < preferences[j][i])
{
pairs[pair_count].winner = j;
pairs[pair_count].loser = i;
pair_count++;
}
}
}
return;
}
1 // Sort pairs in decreasing order by strength of victory
2 void sort_pairs(void)
3 {
4 // fill array with winner preferences
5 int onearr[100] = { 0 };
6 for (int i = 0; i < pair_count; i++)
7 {
8 onearr[i] = preferences[pairs[i].winner][pairs[i].loser];
9 }
10 //sorting function
11 while (1)
12 {
13 int swapped = 0;
14 for (int i = 0; i < pair_count - 1; i++)
15 {
16 if (onearr[i] < onearr[i + 1])
17 {
18 int temp = onearr[i];
19 onearr[i] = onearr[i + 1];
20 onearr[i + 1] = temp;
21 swapped = 1;
22 }
23 }
24 if (swapped == 0)
25 {
26 break;
27 }
28 }
29 return;
30 }
// 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;
}
My question specifically is that the sorting function seems to work fine (I added printf statements all over the place to check if it correctly sorts, and it does) but check50 tells me sort_pairs does not correctly sort pairs. The last two lock_pairs(void) and print_winner(void) I have yet to define.
Thanks in advance
Answer found:
// Sort pairs in decreasing order by strength of victory
void sort_pairs(void)
{
// fill array with winner preferences
int strength[pair_count];
for (int i = 0; i < pair_count; i++)
{
strength[i] = preferences[pairs[i].winner][pairs[i].loser] - preferences[pairs[i].loser][pairs[i].winner];
}
//sorting function
while (1)
{
int swapped = 0;
for (int i = 0; i < pair_count - 1; i++)
{
for (int j = i + 1; j < pair_count; j++)
{
if (strength[i] < strength[j])
{
//sorting pairs
pair tmp = pairs[i];
pairs[i] = pairs[j];
pairs[j] = tmp;
//sorting strength
int tmp2 = strength[j];
strength[j] = strength[i];
strength[i] = tmp2;
}
}
}
if (swapped == 0)
{
break;
}
}
return;
}