In this problem set, we have to write a code that runs the Tideman election as shown in below code snippet.
$ ./tideman Alice Bob Charlie Number of voters: 5 Rank 1: Alice Rank 2: Charlie Rank 3: Bob Rank 1: Alice Rank 2: Charlie Rank 3: Bob Rank 1: Bob Rank 2: Charlie Rank 3: Alice Rank 1: Bob Rank 2: Charlie Rank 3: Alice Rank 1: Charlie Rank 2: Alice Rank 3: Bob Charlie
In the previous posts, I gave you the solution to the cs50 psets 3 plurality problem, and cs50 psets 3 runoff problem.
So the plurality election system and runoff election system have their own advantages and disadvantages. Now, let’s see what is the Tideman election system.
Tideman Election System
Tideman method is also known as the Ranked pairs method. This system was developed in 1987 by Nicolaus Tideman. This system selects a single winner using votes that express preferences. This method can also be used to create a sorted list of winners.
So, let’s get back to the problem set, an initial code is given to us.
Solution
1. The vote function
// Update ranks given a new vote bool vote(int rank, string name, int ranks[]) { // TODO for (int i = 0; i < candidate_count; i++) { if (strcmp(name, candidates[i]) == 0) { ranks[rank] = i; return true; } } return false; }
2. The record_preferences function
// Update preferences given one voter's ranks void record_preferences(int ranks[]) { // TODO for (int i = 0; i < candidate_count; i++) { for (int j = i + 1; j < candidate_count; j++) { preferences[ranks[i]][ranks[j]]++; } } return; }
3. The add_pairs function
// Record pairs of candidates where one is preferred over the other void add_pairs(void) { // TODO 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; }
4. The sort_pairs function
// Sort pairs in decreasing order by strength of victory void sort_pairs(void) { // TODO for (int i = 0; i < pair_count; i++) { int max = i; for (int j = i; j < pair_count; j++) { if (preferences[pairs[j].winner][pairs[j].loser] > preferences[pairs[max].winner][pairs[max].loser]) { max = j; } } pair temp = pairs[i]; pairs[i] = pairs[max]; pairs[max] = temp; } return; }
5. The cycle function
// Check for cycle by checking arrow coming into each candidate bool cycle(int cycle_end, int cycle_start) { // Return true if there is a cycle if (cycle_end == cycle_start) { return true; } // Loop through all the candidates for (int i = 0; i < candidate_count; i++) { if (locked[cycle_end][i]) { if (cycle(i, cycle_start)) { return true; } } } return false; }
6. The lock_pairs function
// Lock pairs into the candidate graph in order, without creating cycles void lock_pairs(void) { // TODO for (int i = 0; i < pair_count; i++) { if (!cycle(pairs[i].loser, pairs[i].winner)) { locked[pairs[i].winner][pairs[i].loser] = true; } } return; }
7. The print_winner function
// Print the winner of the election void print_winner(void) { // TODO for (int i = 0; i < candidate_count; i++) { bool loser = false; for (int j = 0; j < candidate_count; j++) { if (locked[j][i]) { loser = true; break; } } if (loser) { continue; } if (!loser) { printf("%s\n", candidates[i]); } } return; }
Full Code
here is the full code that includes all the functions,
#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); bool cycle(int cycle_end, int cycle_start); 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[]) { // TODO 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[]) { // TODO 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) { // TODO 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; } // Sort pairs in decreasing order by strength of victory void sort_pairs(void) { // TODO for (int i = 0; i < pair_count; i++) { int max = i; for (int j = i; j < pair_count; j++) { if (preferences[pairs[j].winner][pairs[j].loser] > preferences[pairs[max].winner][pairs[max].loser]) { max = j; } } pair temp = pairs[i]; pairs[i] = pairs[max]; pairs[max] = temp; } return; } // Check for cycle by checking arrow coming into each candidate bool cycle(int cycle_end, int cycle_start) { // Return true if there is a cycle if (cycle_end == cycle_start) { return true; } // Loop through all the candidates for (int i = 0; i < candidate_count; i++) { if (locked[cycle_end][i]) { if (cycle(i, cycle_start)) { return true; } } } return false; } // Lock pairs into the candidate graph in order, without creating cycles void lock_pairs(void) { // TODO for (int i = 0; i < pair_count; i++) { if (!cycle(pairs[i].loser, pairs[i].winner)) { locked[pairs[i].winner][pairs[i].loser] = true; } } return; } // Print the winner of the election void print_winner(void) { // TODO for (int i = 0; i < candidate_count; i++) { bool loser = false; for (int j = 0; j < candidate_count; j++) { if (locked[j][i]) { loser = true; break; } } if (loser) { continue; } if (!loser) { printf("%s\n", candidates[i]); } } return; }
Hope this helps you, Good luck!
One Response
Leave a comment sharing your knowledge