https://cs50.harvard.edu/x/2023/psets/3/runoff/#tabulate
Runoff - CS50x 2023
Harvard University's introduction to the intellectual enterprises of computer science and the art of programming.
cs50.harvard.edu
아... 5시간 넘게 걸렸다.
길지 않은 코드이지만 오류가 너무 많이 나서 하나씩 잡는데 너무 오래걸렸다.
1. break; 가 while만 뚫는줄 알았는데, for구문도 뚫어버린다는것(1겹만 뚫는다)
그래서 무한루프가 되어 계속 오류가 남.
2. 총 득표수의 50%를 계산할때 이미 탈락한 후보를 제외하지 않아서 부분적 오류가 계속 남아있었음.
3. 최소 카운트를 찾는데 기준값하나를 정의하고, 그걸 기준으로 그것보다 작으면 그 값으로 대체하고 하는 식으로 selection sort를 하려고 했는데, 초기값을 최대값이 아닌 0으로 잡아버려서 모든 값이 0보다 커서 최소값을 찾지 못했다.
4. 고칠때 실수들을 적어두어야겠다.
#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 // 2차원 데이터임 각각표결 저장
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)
{
// TODO
bool isThere = false;
int candidate_number;
for(int i = 0; i < candidate_count; i++)
{
if (strcmp(name,candidates[i].name) == 0)
{
isThere = true;
candidate_number = i;
};
};
if (isThere)
{
preferences[voter][rank] = candidate_number;
return true;
};
return false;
}
// Tabulate votes for non-eliminated candidates
void tabulate(void)
//투표용지를 돌면서
//1순위 랭크를 돌다가 혹시 떨어진애 나오면
//떨어지지 않은 애가 나올때까지 루프롤 돔..
{
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++;
break;
}
}
}
return;
};
// Print the winner of the election, if there is one
bool print_winner(void)
{
// TODO
int vote_total = 0;
for(int i = 0; i < candidate_count; i++)
{
if(candidates[i].eliminated == false) //eliminated된 후보 제외 이거 없으니 계속 오류남!
{
vote_total = vote_total + candidates[i].votes;
};
};
for(int i = 0; i < candidate_count; i++)
{
if(candidates[i].eliminated == false) //eliminated된 후보 제외 이거 없으니 계속 오류남!
{
if(candidates[i].votes > (vote_total / 2)) // 과반수
{
printf("%s\n",candidates[i].name);
return true;
};
};
};
return false;
}
// Return the minimum number of votes any remaining candidate has
int find_min(void)
{
// TODO
int min_votes = voter_count; // 0아님에 주의
for (int i = 0; i < candidate_count; i++)
{
if (!candidates[i].eliminated)
{
if (candidates[i].votes < min_votes)
{
min_votes = candidates[i].votes;
};
};
};
return min_votes;
}
// Return true if the election is tied between all candidates, false otherwise
bool is_tie(int min)
{
bool tie = true;
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].votes == min)
{
candidates[i].eliminated = true;
};
};
return;
}