Advertisement
bocajbee

tidemanfinal

Apr 24th, 2020
796
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.76 KB | None | 0 0
  1. #include <cs50.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. #define MAX 9  // max number of candidates that can be in the election. 9
  6.  
  7. int preferences[MAX][MAX];  // preferences[i][j] is a 2d array to represent the number of voters who prefer candiate[i] over candidate[j], using an adjacency matrix
  8.  
  9. bool locked[MAX][MAX];  // 2d boolean array, used to keep track of the candidate graph. if locked[i][j] == TRUE, we've locked in the edge pointing from candidate "i" to candidate "j"
  10.  
  11. typedef struct  // struct used to declare each pair, which has a winner & loser
  12. {
  13.     int winner;
  14.     int loser;
  15. }
  16. pair;
  17.  
  18. string candidates[MAX];  // array of strings, for the candidates names, candidate[0] is the 1st candidate. candidate[1] is the 2nd candidate etc...
  19. pair pairs[MAX * (MAX - 1) / 2];  // array of the MAX amount of candidates * (MAX amount of candidates - argc) / 2, so we can fit all of the pair structs in each index of pairs[]
  20.  
  21. int pair_count;  // global variables: pair_count & candidate_count, representing the number of "pairs" & number of "candidates" in the arrays: pairs[] & candidates[]
  22. int candidate_count;
  23.  
  24. bool vote(int rank, string name, int ranks[]);  // function prototypes
  25. void record_preferences(int ranks[]);
  26. void add_pairs(void);
  27. void sort_pairs(void);
  28. void lock_pairs(void);
  29. void print_winner(void);
  30. bool check_cycle(int winner, int loser);
  31.  
  32. int main(int argc, string argv[])
  33. {
  34.     if (argc < 2)  // check for invalid usage
  35.     {
  36.         printf("Usage: tideman [candidate ...]\n");
  37.         return 1;
  38.     }
  39.  
  40.     candidate_count = argc - 1;  // populate array of candidates
  41.     if (candidate_count > MAX)
  42.     {
  43.         printf("Maximum number of candidates is %i\n", MAX);
  44.         return 2;
  45.     }
  46.  
  47.     for (int i = 0; i < candidate_count; i++) // loop through & populate the candidates[] array
  48.     {
  49.         candidates[i] = argv[i + 1]; // take user input for their "candidate" in argv (+1 to exclude ".\tideman") + store it in the candidate[] array
  50.     }
  51.  
  52.     for (int i = 0; i < candidate_count; i++)  // outer nested forloop, to go through 1 row (i) of locked[][] at a time
  53.     {
  54.         for (int j = 0; j < candidate_count; j++)  // inner nested loop, to go through every column (j) of locked[][] before the outer loop executes again, to check the next row
  55.         {
  56.             locked[i][j] = false;  // set the current element at locked[i][j] to FASLE
  57.         }
  58.     }
  59.  
  60.     pair_count = 0;  // set pairs_count at the start of main() to equal 0.
  61.     int voter_count = get_int("Number of voters: ");
  62.     printf("\n");
  63.  
  64.     for (int i = 0; i < voter_count; i++)  // outer nested forloop, to go through every voter declared
  65.     {
  66.         int ranks[candidate_count];  // creates a seperate array of ranks[] for the voter at "i", with as many elements equal to "candidate_count". ranks[i] is this voter's ith preference
  67.  
  68.         for (int j = 0; j < candidate_count; j++)  // inner loop to query for the current voters prefered candidates, until this matches the candidate_count. it will then store these in this voters ranks[] preferences
  69.         {
  70.             string name = get_string("Candiate prefered rank %i: ", j + 1);  // record the candidate rank for the current "voter" at "j" (+1 to make it count from voter 1 insteaf of voter 0).
  71.             if (!vote(j, name, ranks))  // the current value of "j" here represents the current voter being checked, the candidate "name" they picked & the current "ranks[]" 1d array for this voter. This is passed into vote()
  72.             {
  73.                 printf("Invalid vote.\n");
  74.                 return 3;
  75.             }
  76.         }
  77.         printf("Current ranks array %d %d %d:", ranks[0], ranks[1], ranks[2]);
  78.         printf("\n");
  79.         record_preferences(ranks);
  80.  
  81.     }
  82.     printf("\n");
  83.     add_pairs();
  84.     sort_pairs();
  85.     lock_pairs();
  86.     print_winner();
  87.     return 0;
  88. }
  89.  
  90.  
  91. bool vote(int rank, string name, int ranks[])  // update ranks given a new vote. this function takes in the arguments "rank", "name", and "ranks[]"" as mentioned on line 79
  92. {
  93.     for (int i = 0; i < candidate_count; i++)  // loop through against every potential candidate in the election
  94.     {
  95.         if (strcmp(candidates[i], name) == 0)  // check if the user's inputted "name" inpuuted on line 78 matches the current candidate in the candidates[] array looped through above. if TRUE (== 0)
  96.         {
  97.             ranks[rank] = i; // here "i" represents the index of current candidate in the candidates[] array. we update the ranks[] array with the ith candidate index, indicating this voter's current candidate preference to record.
  98.             return true;  // function will return TRUE after grabbing this ith candidate + storing it in the correct index of the ranks[] array (first candidate voter picked into ranks[0], second into ranks[1] etc)
  99.         }
  100.     }
  101.     return false;  // return FALSE if the above is not met, so this vote() function is looped through again in main()
  102. }
  103. void record_preferences(int ranks[])  // record each voter's preferences[][] by referencing their previous ranks[]
  104. {
  105.     printf("\n");
  106.     for (int i = 0; i < candidate_count; i++)   // outer forloop to increment "i" (for the row candidate) from 0, representing the current index of the candidate rank[] we want to reference in the 2d preferences[HERE][] array accurately
  107.     {
  108.         for (int j = 0; j < candidate_count; j++)  // inner forloop to increment a j counting variable (for the column candidate) from 0 to represent the current index of the candidate rank[] we want to reference in the 2d preferences[][HERE] array accurately
  109.         {
  110.             if (i < j)
  111.             {
  112.                 preferences[ranks[i]][ranks[j]]++; // add 1 tally mark to prefrences[i][j] in accordance to the current value of the counting variables i and j in the nested forloops, in context to the candidates in the 1d ranks[] array
  113.             }
  114.         }
  115.     }
  116. }
  117.  
  118. void add_pairs(void)  // Record pairs of candidates where one is preferred over the other
  119. {
  120.     for (int i = 0; i < candidate_count; i++) // outer forloop to increment a i counting variable (for the row candidate) from 0 to represent the current index of the candidate in the rows of preferences[HERE][]
  121.     {
  122.         for (int j = 0; j < candidate_count; j++)  // inner forloop to increment a j counting variable (for the column candidate) from 0 to represent the current index of the candidate in the columns of preferences[][HERE]
  123.         {
  124.             if (preferences[i][j] > preferences[j][i])  // if whatever is in preferences[i][j] has a greater value than in preferences[j][i] (that the candidate in preferences[i](Row) has more tally marks than the candidate in preference [j](Column)
  125.             {
  126.                 pairs[pair_count].winner = i;  // update the [current index] of the pairs[] array and set the value taken from preferences[i] (column) to be the winner
  127.                 pairs[pair_count].loser = j;  // update the [current index] of the pairs[] array and set the value taken from preferences[j] (row) to be the loser
  128.                 pair_count++; // update 1 count to the paircount to tally the total number of pairs counted in this program
  129.             }
  130.         }
  131.     }
  132.     return;
  133. }
  134.  
  135. void sort_pairs(void)
  136. {
  137.   while (1)  // this while loop is set to "true (1)" and it'll run forever until an exit condition is met
  138.   {
  139.       int swapped = 0;  // counting variable to indicate if a swap has been currently performed going through the bubble sort or not. This is set to 0 at the start of this while loop every time.
  140.       pair temp;  // declaring a temp variable to store variables we want to swap in
  141.  
  142.       for (int i = 0; i < pair_count -1; i++)  // Loop through entire array of pairs[]. In a bubble sort , we need to -1 off of the pair_count being checked against. Because there's nothing to compare the last element to.
  143.       {
  144.           // check if the margin difference between the candidate.winner - the candidate.loser in [i] is < the margin difference between the candidate.winner - the candidate.loser in [i + 1]
  145.           if (preferences[pairs[i].winner][pairs[i].loser] - preferences[pairs[i].loser][pairs[i].winner] < preferences[pairs[i + 1].winner][pairs[i + 1].loser] - preferences[pairs[i].loser][pairs[i].winner])
  146.           {
  147.               temp = pairs[i];  // take the data in pairs[i] and move it inside of temp
  148.               pairs[i] = pairs[i + 1];  // take the data in pairs[i + 1] and move it to pairs[i]
  149.               pairs[i + 1] = temp;  // take the data we stores in temp and move it into [i +1] to complete the swap.
  150.               swapped = 1;  // update swapped to == 1 to indicate the full swap has been coomplete
  151.           }
  152.       }
  153.  
  154.       if (swapped == 0) // check if swapped equals "false"
  155.       {
  156.           break;  // if it does, break the loop
  157.       }
  158.   }
  159. }
  160.  
  161. void lock_pairs(void)  // lock pairs into the candidate graph in order, without creating cycles
  162. {
  163.     for (int i = 0; i < pair_count; i++)  // forloop through pairs[], to get the pairs with the highest strengh of victory (starting with pairs[0])
  164.     {
  165.         if (!check_cycle(pairs[i].winner, pairs[i].loser))  // if check_cycle returns FALSE (no cycle will be created using check_cycles()) for the current .winner @ pairs[i] and .loser @ pairs[i]
  166.         {
  167.             locked[pairs[i].winner][pairs[i].loser] = true;  // set locked(for this)[.winner][.loser] at pairs[i] to TRUE, drawing a line;
  168.         }
  169.         printf("Locked[i][j] %s \n", locked[pairs[i].winner][pairs[i].loser] ? "true" : "false");
  170.     }
  171.     return;
  172. }
  173.  
  174. bool check_cycle(int start, int end)  // "int start" is "pairs[i].winner" & "int end" is the "pairs[i].loser"
  175. {
  176.     if (locked[end][start] == true) // base case, if a path already exists between the ending node and starting node
  177.     {
  178.         return true; // return "true", indacating a edge exists between this starting node (candidate) and ending node (candidate)
  179.     }
  180.     // recursive case, that will track if an edge exists between any two nodes, & plot new startinh nodes, to see if a backedge exists between any 2 nodes in the graph
  181.     for (int i = 0; i < candidate_count; i++)   // loop through all possible candidates[] in the graph
  182.     {
  183.         if ((locked[i][start]) == true) // if a path already exists between the ending node at [i] and the orignal starting node
  184.         {
  185.             if (check_cycle(i, end) == true)  // pass in the ending node at [i] as the new starting node + check if a path already exists between it & the original ending node
  186.             {
  187.                 return true;
  188.             }
  189.         }
  190.     }
  191.     return false; // else return FALSE if no edges can be found betweeb the two nodes
  192.  }
  193.  
  194. void print_winner(void) // print the winner of the election
  195. {
  196.     bool winner;
  197.  
  198.     for (int i = 0; i < candidate_count; i++)  // nested outer loop, through all rows in locked[i][], checking for candidate [i]
  199.     {
  200.         winner = true; // set winner to TRUE on each passthrough of this loop
  201.  
  202.         for (int j = 0; j < candidate_count; j++) // nested inner loop, through all of the columns in locked[][] for candidate [j] with this inner nested loop
  203.         {
  204.             if (locked[j][i] == true) // if at anyt point when looping through the columns of candidates in [j], if we find any candidate at j with an arrow pointing ot them from a candidate at [i]
  205.             {
  206.                 winner = false; // assign the value of "false" to winner on this passthrough of this loop
  207.             }
  208.         }
  209.         // if after looping through the entire locked[][] 2d array column by column, every index in locked [j][i] was set to "false"
  210.         // determining candidate[j] has NO other candidates with an arrow pointing torwards them, winner is set to true
  211.         if (winner == true)
  212.         {
  213.             printf("%s\n", candidates[i]);
  214.         }
  215.     }
  216.     return;
  217. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement