Advertisement
cd62131

Nuts and Bolts match problem

Nov 5th, 2017
285
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.65 KB | None | 0 0
  1. #include <ctype.h>
  2. #include <stdbool.h>
  3. #include <stddef.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <time.h>
  7.  
  8. typedef char object;
  9.  
  10. typedef struct {
  11.   object kind;
  12. } nut;
  13.  
  14. typedef struct {
  15.   object kind;
  16. } bolt;
  17.  
  18. typedef enum {
  19.   NUT, BOLT
  20. } screw;
  21.  
  22. typedef struct {
  23.   screw type;
  24.   union {
  25.     nut *n;
  26.     bolt *b;
  27.   } val;
  28. } nutbolt;
  29.  
  30. typedef struct {
  31.   size_t i, j, match;
  32. } sort_status;
  33.  
  34. static nutbolt *new_nutbolt(screw, object);
  35. static size_t size_serial(const object, const object);
  36. static int random_int_range(int, int);
  37. static void shuffle_nutbolt(nutbolt **, size_t);
  38. static nutbolt **init_nutbolt(screw, object, object);
  39. static object next_object(object);
  40. static void sort_nutbolt(nutbolt **, nutbolt **, size_t, size_t);
  41. static sort_status *partition(nutbolt **, nutbolt *, size_t, size_t);
  42. static void swap_nutbolt(nutbolt **, nutbolt **);
  43. static int compare_nutbolt(nutbolt *, nutbolt *);
  44. static int compare_object(object, object);
  45. static void print_nutbolt(nutbolt **, size_t);
  46. static void free_nutbolt(nutbolt **, size_t);
  47.  
  48. int main(void) {
  49.   nutbolt **nuts = init_nutbolt(NUT, 'A', 'Z');
  50.   nutbolt **bolts = init_nutbolt(BOLT, 'a', 'z');
  51.   size_t size = size_serial('A', 'Z');
  52.   print_nutbolt(nuts, size);
  53.   print_nutbolt(bolts, size);
  54.   sort_nutbolt(nuts, bolts, 0, size - 1);
  55.   print_nutbolt(nuts, size);
  56.   print_nutbolt(bolts, size);
  57.   free_nutbolt(nuts, size);
  58.   free_nutbolt(bolts, size);
  59. }
  60.  
  61. static nutbolt *new_nutbolt(screw type, object o) {
  62.   nutbolt *new = calloc(1, sizeof(new));
  63.   new->type = type;
  64.   if (type == NUT) {
  65.     new->val.n = calloc(1, sizeof(new->val.n));
  66.     new->val.n->kind = o;
  67.   } else {
  68.     new->val.b = calloc(1, sizeof(new->val.b));
  69.     new->val.b->kind = o;
  70.   }
  71.   return new;
  72. }
  73.  
  74. static size_t size_serial(const object start, const object end) {
  75.   return (char) end - (char) start + 1;
  76. }
  77.  
  78. static int random_int_range(int lower, int upper) {
  79.   static bool first = true;
  80.   if (first) {
  81.     srand(time(NULL));
  82.     first = false;
  83.   }
  84.   return lower + rand() % (upper - lower + 1);
  85. }
  86.  
  87. static void shuffle_nutbolt(nutbolt **nb, size_t size) {
  88.   for (size_t i = size - 1; i > 0; --i) {
  89.     size_t j = random_int_range(0, i);
  90.     nutbolt *temp = nb[i];
  91.     nb[i] = nb[j];
  92.     nb[j] = temp;
  93.   }
  94. }
  95.  
  96. static nutbolt **init_nutbolt(screw type, object begin, object end) {
  97.   size_t size = size_serial(begin, end);
  98.   nutbolt **new = calloc(size, sizeof(new));
  99.   object o = begin;
  100.   for (size_t i = 0; i < size; ++i, o = next_object(o)) {
  101.     new[i] = new_nutbolt(type, o);
  102.   }
  103.   shuffle_nutbolt(new, size);
  104.   return new;
  105. }
  106.  
  107. static object next_object(object o) {
  108.   return o + 1;
  109. }
  110.  
  111. static void sort_nutbolt(nutbolt **nuts, nutbolt **bolts, size_t left, size_t right) {
  112.   if (left >= right) {
  113.     return;
  114.   }
  115.   nutbolt *pivot = bolts[random_int_range(left, right)];
  116.   sort_status *st = partition(nuts, pivot, left, right);
  117.   sort_status *dummy = partition(bolts, nuts[st->match], left, right);
  118.   free(dummy);
  119.   sort_nutbolt(nuts, bolts, left, st->i - 1);
  120.   sort_nutbolt(nuts, bolts, st->j + 1, right);
  121.   free(st);
  122. }
  123.  
  124. static sort_status *partition(nutbolt **nb, nutbolt *p, size_t l, size_t r) {
  125.   size_t i = l, j = r;
  126.   int match = -1, cmp1, cmp2;
  127.   while (true) {
  128.     while (i <= r && (cmp1 = compare_nutbolt(nb[i], p)) <= 0) {
  129.       if (cmp1 == 0) {
  130.         match = i;
  131.       }
  132.       ++i;
  133.     }
  134.     while ((cmp2 = compare_nutbolt(nb[j], p)) > 0) {
  135.       --j;
  136.     }
  137.     if (i >= j) {
  138.       if (cmp2 == 0) {
  139.         match = j;
  140.       }
  141.       break;
  142.     }
  143.     swap_nutbolt(&nb[i], &nb[j]);
  144.     if (cmp2 == 0) {
  145.       match = i;
  146.     }
  147.     ++i;
  148.     --j;
  149.   }
  150.   sort_status *st = calloc(1, sizeof(st));
  151.   st->i = i;
  152.   st->j = j;
  153.   st->match = match;
  154.   return st;
  155. }
  156.  
  157. static void swap_nutbolt(nutbolt **v1, nutbolt **v2) {
  158.   nutbolt *t = *v1;
  159.   *v1 = *v2;
  160.   *v2 = t;
  161. }
  162.  
  163. static int compare_nutbolt(nutbolt *v1, nutbolt *v2) {
  164.   if (v1->type == NUT) {
  165.     return compare_object(v1->val.n->kind, v2->val.b->kind);
  166.   }
  167.   return compare_object(v1->val.b->kind, v2->val.n->kind);
  168. }
  169.  
  170. static int compare_object(object o1, object o2) {
  171.   int diff = 'A' - 'a';
  172.   if (isupper(o1)) {
  173.     diff = -diff;
  174.   }
  175.   return o1 + diff - o2;
  176. }
  177.  
  178. static void print_nutbolt(nutbolt **nb, size_t size) {
  179.   if (nb[0]->type == NUT) {
  180.     for (size_t i = 0; i < size; ++i) {
  181.       printf("%c", nb[i]->val.n->kind);
  182.     }
  183.   } else {
  184.     for (size_t i = 0; i < size; ++i) {
  185.       printf("%c", nb[i]->val.b->kind);
  186.     }
  187.   }
  188.   puts("");
  189. }
  190.  
  191. static void free_nutbolt(nutbolt **nb, size_t size) {
  192.   for (size_t i = 0; i < size; ++i) {
  193.     free(nb[i]);
  194.   }
  195.   free(nb);
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement