Advertisement
bocajbee

tideman2

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