-
-
Save AnimeshRy/489d3c19db9d179c7c562bad24c4b3ee to your computer and use it in GitHub Desktop.
#include <cs50.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#include <math.h> | |
// Max voters and candidates | |
#define MAX_VOTERS 100 | |
#define MAX_CANDIDATES 9 | |
// preferences[i][j] is jth preference for voter i(2d array) | |
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 | |
//passed i,j and name of the candidate the user entered, look at line 77 | |
bool vote(int voter, int rank, string name) | |
{ | |
bool exist = false; | |
for (int i = 0; i < candidate_count; i++) | |
{ | |
//check if name is present in the candidates entered by the user by camparing two strings | |
//strcmp is checking for the name and camparing it to the candidates array location 'i' which starts according to the for loop above | |
if (strcmp(name, candidates[i].name) == 0) | |
{ | |
//if you found the person is present then add that number as a rank of the candidate in the preferences array | |
//suppose this is a 2d array and the preference array is adding the preference number on a specific poistion so | |
// here ex - preferences[0][0] = i (the rank preferences from the candidate count) | |
// [i][][][] | |
// [][][][] | |
// [][][][] | |
// [][][][] | |
preferences[voter][rank] = i; | |
exist = true; | |
break; | |
//This is a bool conditions which will become true, again look at line 77 | |
} | |
} | |
return exist; | |
} | |
// Tabulate votes for non-eliminated candidates | |
void tabulate(void) | |
{ | |
// TODO | |
for (int i = 0; i < voter_count; i++) | |
{ | |
for (int j = 0; j < candidate_count; j++) | |
{ | |
if (candidates[preferences[i][j]].eliminated == false) | |
{ | |
candidates[preferences[i][j]].votes += 1; | |
break; | |
} | |
} | |
} | |
return; | |
} | |
// Print the winner of the election, if there is one | |
bool print_winner(void) | |
{ | |
// TODO | |
for (int i = 0; i < candidate_count; i++) | |
{ | |
string most = candidates[i].name; | |
if (candidates[i].votes > voter_count / 2) | |
{ | |
printf("%s\n", most); | |
return true; | |
} | |
} | |
return false; | |
} | |
// Return the minimum number of votes any remaining candidate has | |
int find_min(void) | |
{ | |
int minvotes = voter_count; | |
for (int i = 0; i < candidate_count; i++) | |
{ | |
if (candidates[i].eliminated == false && candidates[i].votes < minvotes) | |
{ | |
minvotes = candidates[i].votes; | |
} | |
} | |
return minvotes; | |
} | |
// Return true if the election is tied between all candidates, false otherwise | |
bool is_tie(int minvotes) | |
{ | |
for (int i = 0; i < candidate_count; i++) | |
{ | |
if (candidates[i].eliminated == false && candidates[i].votes != minvotes) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
// Eliminate the candidate (or candidiates) in last place | |
void eliminate(int minvotes) | |
{ | |
for (int i = 0; i < candidate_count; i++) | |
if (candidates[i].votes == minvotes) | |
{ | |
candidates[i].eliminated = true; | |
} | |
return; | |
} |
Hello @AnimeshRy
On line 204 of your code, it says "return minvotes". I understand that it doesn't work otherwise so I would like to inquire about the following questions:
What is the logic behind that statement?
Why can't it "return true" or anything else?
Thanks in advance for your help!Hi, I think I might be able to answer your question. In the return logic of a boolean function you need in fact to return true or false value. But that is a function made to return an integer instead, so the return value of the function must be of the same type it was declared in the first place. Consider the function declaration:
int find_min(void)
This statement defines the return value that function must provide. Which in this case is the integer value stored inminvotes
, that will later be used by other functions to know the fewest number of votes one or more of the candidates have.Additionally I would like to ask about a doubt myself to @AnimeshRy or any person willing.
When I run check50 it gives me these red warnings:
:( print_winner prints name when someone has a majority
print_winner did not print winner of election
:( print_winner returns true when someone has a majority
print_winner did not print winner and then return true
Below is my print_winner() function which is very similar to the one presented by AnimeshRy and yet it does not seem to be correct. I went through debugging every step and even compared some other functions to see if I was missing something. But the thing is that it seems to check out... I'm cracking my head on this. Here's the function:
bool print_winner(void) { int half = (round)(voter_count / 2); for (int i = 0; i < candidate_count; i++) { if (candidates[i].votes > half) { printf("%s", candidates[i].name); return true; } } return false; }
Every other checkpoint is met in the test. Any ideas what could be giving this?
You don't need the round function when you are already storing the values in a int. Also you are casting the round function wrong here.
round(var)
is the correct way. But none of them is the problem in your code, the most likely problem is not using the"\n" in your print statement. Check50 checks the output from top to bottom line by line so a wrong newline is a problem. I haven't tried your function for check50 but newline being a problem is highly probable.
Hello @AnimeshRy
On line 204 of your code, it says "return minvotes". I understand that it doesn't work otherwise so I would like to inquire about the following questions:
What is the logic behind that statement?
Why can't it "return true" or anything else?
Thanks in advance for your help!Hi, I think I might be able to answer your question. In the return logic of a boolean function you need in fact to return true or false value. But that is a function made to return an integer instead, so the return value of the function must be of the same type it was declared in the first place. Consider the function declaration:
int find_min(void)
This statement defines the return value that function must provide. Which in this case is the integer value stored inminvotes
, that will later be used by other functions to know the fewest number of votes one or more of the candidates have.Additionally I would like to ask about a doubt myself to @AnimeshRy or any person willing.
When I run check50 it gives me these red warnings:
:( print_winner prints name when someone has a majority
print_winner did not print winner of election
:( print_winner returns true when someone has a majority
print_winner did not print winner and then return true
Below is my print_winner() function which is very similar to the one presented by AnimeshRy and yet it does not seem to be correct. I went through debugging every step and even compared some other functions to see if I was missing something. But the thing is that it seems to check out... I'm cracking my head on this. Here's the function:
bool print_winner(void) { int half = (round)(voter_count / 2); for (int i = 0; i < candidate_count; i++) { if (candidates[i].votes > half) { printf("%s", candidates[i].name); return true; } } return false; }
Every other checkpoint is met in the test. Any ideas what could be giving this?
@TheoMarriot1
Thank you so much for explaining that concept to me. Good luck in your coding journey!
Hello @AnimeshRy
On line 204 of your code, it says "return minvotes". I understand that it doesn't work otherwise so I would like to inquire about the following questions:
What is the logic behind that statement?
Why can't it "return true" or anything else?
Thanks in advance for your help!Hi, I think I might be able to answer your question. In the return logic of a boolean function you need in fact to return true or false value. But that is a function made to return an integer instead, so the return value of the function must be of the same type it was declared in the first place. Consider the function declaration:
int find_min(void)
This statement defines the return value that function must provide. Which in this case is the integer value stored inminvotes
, that will later be used by other functions to know the fewest number of votes one or more of the candidates have.
Additionally I would like to ask about a doubt myself to @AnimeshRy or any person willing.
When I run check50 it gives me these red warnings:
:( print_winner prints name when someone has a majority
print_winner did not print winner of election
:( print_winner returns true when someone has a majority
print_winner did not print winner and then return true
Below is my print_winner() function which is very similar to the one presented by AnimeshRy and yet it does not seem to be correct. I went through debugging every step and even compared some other functions to see if I was missing something. But the thing is that it seems to check out... I'm cracking my head on this. Here's the function:bool print_winner(void) { int half = (round)(voter_count / 2); for (int i = 0; i < candidate_count; i++) { if (candidates[i].votes > half) { printf("%s", candidates[i].name); return true; } } return false; }
Every other checkpoint is met in the test. Any ideas what could be giving this?
You don't need the round function when you are already storing the values in a int. Also you are casting the round function wrong here.
round(var)
is the correct way. But none of them is the problem in your code, the most likely problem is not using the"\n" in your print statement. Check50 checks the output from top to bottom line by line so a wrong newline is a problem. I haven't tried your function for check50 but newline being a problem is highly probable.
Hi! Thanks for pointing it out, I later actually noticed that and removed from my actual code (it was a leftover of some float conversion strategy I tried earlier that also didn't work), but as you said it wasn't the root of the problem...
I will try placing a newline in print to see if it works then
Hello @AnimeshRy
On line 204 of your code, it says "return minvotes". I understand that it doesn't work otherwise so I would like to inquire about the following questions:
What is the logic behind that statement?
Why can't it "return true" or anything else?
Thanks in advance for your help!Hi, I think I might be able to answer your question. In the return logic of a boolean function you need in fact to return true or false value. But that is a function made to return an integer instead, so the return value of the function must be of the same type it was declared in the first place. Consider the function declaration:
int find_min(void)
This statement defines the return value that function must provide. Which in this case is the integer value stored inminvotes
, that will later be used by other functions to know the fewest number of votes one or more of the candidates have.
Additionally I would like to ask about a doubt myself to @AnimeshRy or any person willing.
When I run check50 it gives me these red warnings:
:( print_winner prints name when someone has a majority
print_winner did not print winner of election
:( print_winner returns true when someone has a majority
print_winner did not print winner and then return true
Below is my print_winner() function which is very similar to the one presented by AnimeshRy and yet it does not seem to be correct. I went through debugging every step and even compared some other functions to see if I was missing something. But the thing is that it seems to check out... I'm cracking my head on this. Here's the function:bool print_winner(void) { int half = (round)(voter_count / 2); for (int i = 0; i < candidate_count; i++) { if (candidates[i].votes > half) { printf("%s", candidates[i].name); return true; } } return false; }
Every other checkpoint is met in the test. Any ideas what could be giving this?
@TheoMarriot1
Thank you so much for explaining that concept to me. Good luck in your coding journey!
Glad I could help! Good luck to you as well (:
Hello @AnimeshRy
On line 204 of your code, it says "return minvotes". I understand that it doesn't work otherwise so I would like to inquire about the following questions:
What is the logic behind that statement?
Why can't it "return true" or anything else?
Thanks in advance for your help!Hi, I think I might be able to answer your question. In the return logic of a boolean function you need in fact to return true or false value. But that is a function made to return an integer instead, so the return value of the function must be of the same type it was declared in the first place. Consider the function declaration:
int find_min(void)
This statement defines the return value that function must provide. Which in this case is the integer value stored inminvotes
, that will later be used by other functions to know the fewest number of votes one or more of the candidates have.
Additionally I would like to ask about a doubt myself to @AnimeshRy or any person willing.
When I run check50 it gives me these red warnings:
:( print_winner prints name when someone has a majority
print_winner did not print winner of election
:( print_winner returns true when someone has a majority
print_winner did not print winner and then return true
Below is my print_winner() function which is very similar to the one presented by AnimeshRy and yet it does not seem to be correct. I went through debugging every step and even compared some other functions to see if I was missing something. But the thing is that it seems to check out... I'm cracking my head on this. Here's the function:bool print_winner(void) { int half = (round)(voter_count / 2); for (int i = 0; i < candidate_count; i++) { if (candidates[i].votes > half) { printf("%s", candidates[i].name); return true; } } return false; }
Every other checkpoint is met in the test. Any ideas what could be giving this?
You don't need the round function when you are already storing the values in a int. Also you are casting the round function wrong here.
round(var)
is the correct way. But none of them is the problem in your code, the most likely problem is not using the"\n" in your print statement. Check50 checks the output from top to bottom line by line so a wrong newline is a problem. I haven't tried your function for check50 but newline being a problem is highly probable.
Hi! Thanks for pointing it out, I later actually noticed that and removed from my actual code (it was a leftover of some float conversion strategy I tried earlier that also didn't work), but as you said it wasn't the root of the problem...
I will try placing a newline in print to see if it works then
It was, in fact, the new line... This got me hooked for almost a week, ngl feels kinda embarrasing... 😅
@AnimeshRy I don't know what I would do without you. Really appreciate the help! 🥇
Hey... I am a new junior in cs50.. So please can u make me understand the meaning of line 54 from where the for loop starts. What is that for loop representing??
I will be really obliged for your answer...
candidates[preferences[i][j]].votes
Can someone explain how these two things got combined? I thought preferences array was separate, and not totally understanding how we can just put it into the candidate struct variable. I am very new to any kind of programming, and wasn't sure what to even google to find this answer.
Also, if anyone has a good site they can recommend for some of the basic functions/rules of C.
candidates[preferences[i][j]].votes
Can someone explain how these two things got combined? I thought preferences array was separate, and not totally understanding how we can just put it into the candidate struct variable. I am very new to any kind of programming, and wasn't sure what to even google to find this answer.Also, if anyone has a good site they can recommend for some of the basic functions/rules of C.
I remember being very confused as well with programming, but it will definitely get better :).
Now, for your question. With candidates[preferences[i][j]].votes, you are indicating the number of votes the candidates has, in each voters preference.
Let me implement this more graphically!
So, when implementing the below function:
void tabulate(void)
{
// TODO
for (int i = 0; i < voter_count; i++)
{
for (int j = 0; j < candidate_count; j++)
{
if (candidates[preferences[i][j]].eliminated == false) \ if your candidate's elimination status in voters [i][j] is FALSE, thus not eliminated, do the below
{
candidates[preferences[i][j]].votes += 1; \ this just increments the above candidates votes by 1.
break;
}
}
}
return;
}
Now, candidates[preference[i][j]].votes indicates the amount of votes each candidate has in each voters preference array.
I hope I explained that clearly, but if you have any questions, please, please, please DO NOT hesitate to add another reply. @tara8970
Thanks very much!
can anyone tell me what this message mean ?
linker command failed with exit code 1 (use -v to see invocation)
: recipe for target 'runoff' failed
make: *** [runoff] Error 1
can anyone tell me what this message mean ?
linker command failed with exit code 1 (use -v to see invocation)
: recipe for target 'runoff' failed
make: *** [runoff] Error 1
Maybe you are not using the make statement right. Select the right directory and use make runoff
to make it work. Make files is like a automation tool where the compilation and execution is done together rather than using clang -o file file.o
. If these steps don't work, make a new file in a new dir and try again.
can anyone tell me what this message mean ?
linker command failed with exit code 1 (use -v to see invocation)
: recipe for target 'runoff' failed
make: *** [runoff] Error 1Maybe you are not using the make statement right. Select the right directory and use
make runoff
to make it work. Make files is like a automation tool where the compilation and execution is done together rather than usingclang -o file file.o
. If these steps don't work, make a new file in a new dir and try again.
i'll try again ty so much
Make sure you made your runoff.c in runoff and not just out in pset2 or whatever it is. It should be indented under runoff, not in line with the pset number. Best regards Tara Green-Webber Administrative Manager - Xconditioning [email protected] 250.617.9838
…
On Oct 16, 2020, at 9:24 AM, Animesh @.***> wrote: @AnimeshRy commented on this gist. can anyone tell me what this message mean ? linker command failed with exit code 1 (use -v to see invocation) : recipe for target 'runoff' failed make: *** [runoff] Error 1 Maybe you are not using the make statement right. Select the right directory and use make runoff to make it work. Make files is like a automation tool where the compilation and execution is done together rather than using clang -o file file.o. If these steps don't work, make a new file in a new dir and try again. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.
will make sure of it thank you really !
In line 165 and 167, why do you use candidates[preferences[i][j]].eliminated instead of candidates[i].eliminated?
See above, we used two loops and are iterating over all voters who gave votes to all the candidates and where did we save the votes on these voters? preferences[i][j]
Shouldn't we only be updating preferences[i][0].votes
since second-place votes shouldn't be counted the first time around?
I had applied the similar logic for find_min() function but it shows error in check 50 command. Isn't your code showing the error
:( find_min returns minimum when all candidates are tied
find_min did not identify correct minimum
:( find_min ignores eliminated candidates
find_min did not identify correct minimum
Because you didn't set candidates[i].eliminated == true.
In this case, it will return true if you have already eliminated some candidates.
try this
bool is_tie(int min) { for (int c = 0; c < candidate_count; c++) { if (candidates[c].eliminated == false && candidates[c].votes != min) { return false; } else if (candidates[c].eliminated == true) { return false; } } return true; }
candidates[preferences[i][j]].votes
Can someone explain how these two things got combined? I thought preferences array was separate, and not totally understanding how we can just put it into the candidate struct variable. I am very new to any kind of programming, and wasn't sure what to even google to find this answer.
Also, if anyone has a good site they can recommend for some of the basic functions/rules of C.I remember being very confused as well with programming, but it will definitely get better :).
Now, for your question. With candidates[preferences[i][j]].votes, you are indicating the number of votes the candidates has, in each voters preference.
Let me implement this more graphically!
So, when implementing the below function:void tabulate(void)
{
// TODO
for (int i = 0; i < voter_count; i++)
{
for (int j = 0; j < candidate_count; j++)
{
if (candidates[preferences[i][j]].eliminated == false) \ if your candidate's elimination status in voters [i][j] is FALSE, thus not eliminated, do the below
{
candidates[preferences[i][j]].votes += 1; \ this just increments the above candidates votes by 1.
break;
}
}} return;
}
Now, candidates[preference[i][j]].votes indicates the amount of votes each candidate has in each voters preference array.
I hope I explained that clearly, but if you have any questions, please, please, please DO NOT hesitate to add another reply. @tara8970
Won't that make you add votes for all the [voters,candidates] array not only [voters,0] in the first iteration?
i'm getting this when making runoff
runoff.c:78:20: error: implicit declaration of function 'print_winnner' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
bool won = print_winnner();
why you include #include <stdbool.h> & #include <math.h>????
I really appreciate your work man, you are helping students to solve mind-boggling problem sets. And your explanation is very easy to understand.
but, there is only one thing I am facing a problem with, I took references from many other answers as well but the same issues I am having. I am unable to visualize the pseudo code for the is_tie function, I mean, I can't able to visualize what it is doing. Can you elaborate on the pseudo-code for it?
When it will give true or when false.
It will be very helpful.
thanks for your work on this mind-boggling problem! Can someone explain why is_tie works though? I really could not understand your reasoning behind this function :/
Check CS50 is giving me this response:
:( print_winner prints name when someone has a majority
print_winner did not print winner of election
:( print_winner returns true when someone has a majority
print_winner did not print winner and then return true
:( print_winner returns false when nobody has a majority
print_winner did not return false
:( print_winner returns false when leader has exactly 50% of vote
print_winner did not return false
and this is my print_winner function:
bool print_winner(void)
{
for ( int i = 0; i < candidate_count; i++ )
{
if (candidates[i].votes > (candidate_count / 2))
{
printf("%s\n", candidates[i].name);
return true;
}
}
return false;
}
I am not able to understand where the problem is, if anybody can point it out for me it'll be a huge help.
Thanks in advance for your help
please help me because as I run this code it is not compiling properly instead after entering one rank is giving the output of invalid .
Hi, I think I might be able to answer your question. In the return logic of a boolean function you need in fact to return true or false value. But that is a function made to return an integer instead, so the return value of the function must be of the same type it was declared in the first place. Consider the function declaration:
int find_min(void)
This statement defines the return value that function must provide. Which in this case is the integer value stored in
minvotes
, that will later be used by other functions to know the fewest number of votes one or more of the candidates have.Additionally I would like to ask about a doubt myself to @AnimeshRy or any person willing.
When I run check50 it gives me these red warnings:
:( print_winner prints name when someone has a majority
print_winner did not print winner of election
:( print_winner returns true when someone has a majority
print_winner did not print winner and then return true
Below is my print_winner() function which is very similar to the one presented by AnimeshRy and yet it does not seem to be correct. I went through debugging every step and even compared some other functions to see if I was missing something. But the thing is that it seems to check out... I'm cracking my head on this. Here's the function:
Every other checkpoint is met in the test. Any ideas what could be giving this?