Advertisement
Guest User

spreadsheet.c

a guest
Aug 18th, 2014
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.11 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5.  
  6. struct position {
  7.     short col, row;
  8.     struct position *next;
  9. };
  10.  
  11. struct position *position(short col, short row, struct position *next)
  12. {
  13.     struct position *cell = malloc(sizeof(struct position));
  14.     if (cell == NULL)
  15.         abort();
  16.     cell->col = col;
  17.     cell->row = row;
  18.     cell->next = next;
  19.     return cell;
  20. }
  21.  
  22. inline void position_free(struct position *p)
  23. {
  24.     free(p);  // fully abstract allocation
  25. }
  26.  
  27. struct position *position_parse(const char **s)
  28. {
  29.     struct position *out = position(0, 0, NULL);
  30.     while (isalnum(**s)) {
  31.         if (isalpha(**s))
  32.             out->col = out->col * 26 + (**s - 'A') + 1;
  33.         else
  34.             out->row = out->row * 10 + (**s - '0');
  35.         (*s)++;
  36.     }
  37.     out->col--;
  38.     out->row--;
  39.     return out;
  40. }
  41.  
  42. int position_cmp(const void *a, const void *b)
  43. {
  44.     struct position **pa = (struct position **) a,
  45.                     **pb = (struct position **) b;
  46.     if ((**pa).col == (**pb).col)
  47.         return (**pa).row - (**pb).row;
  48.     else
  49.         return (**pa).col - (**pb).col;
  50. }
  51.  
  52. void selection_free(struct position *selection)
  53. {
  54.     while (selection) {
  55.         struct position *last = selection;
  56.         selection = selection->next;
  57.         position_free(last);
  58.     }
  59. }
  60.  
  61. struct position *selection_range(struct position *start, struct position *end)
  62. {
  63.     struct position *head = start;
  64.     for (int col = start->col; col <= end->col; col++) {
  65.         for (int row = start->row; row <= end->row; row++) {
  66.             if (row == end->row && col == end->col)
  67.                 head = head->next = end;
  68.             else if (row != start->row || col != start->col)
  69.                 head = head->next = position(col, row, NULL);
  70.         }
  71.     }
  72.     return start;
  73. }
  74.  
  75. struct position *selection_last(struct position *selection)
  76. {
  77.     if (selection == NULL)
  78.         return NULL;
  79.     while (selection->next)
  80.         selection = selection->next;
  81.     return selection;
  82. }
  83.  
  84. size_t selection_size(const struct position * selection)
  85. {
  86.     size_t size;
  87.     for (size = 0; selection; selection = selection->next, size++);
  88.     return size;
  89. }
  90.  
  91. struct position *selection_sort(struct position *selection)
  92. {
  93.     if (selection == NULL)
  94.         return NULL;
  95.     size_t size = selection_size(selection);
  96.     struct position *positions[size];
  97.     struct position *fill = selection;
  98.     for (size_t i = 0; i < size; fill = fill->next, i++)
  99.         positions[i] = fill;
  100.     qsort(positions, size, sizeof(struct position *), position_cmp);
  101.     for (size_t i = 0; i < size - 1; i++)
  102.         positions[i]->next = positions[i + 1];  // relink
  103.     positions[size - 1]->next = NULL;
  104.     return positions[0];
  105. }
  106.  
  107. struct position *selection_uniq(struct position *selection)
  108. {
  109.     if (selection == NULL)
  110.         return NULL;
  111.     struct position *head = selection = selection_sort(selection);
  112.     while (head->next) {
  113.         struct position *next = head->next;
  114.         if (position_cmp(&head, &next) == 0) {
  115.             head->next = next->next;
  116.             position_free(next);
  117.         } else {
  118.             head = next;
  119.         }
  120.     }
  121.     return selection;
  122. }
  123.  
  124. struct position *selection_diff(struct position *a, struct position *b)
  125. {
  126.     struct position head = { 0, 0, a };
  127.     a = &head;
  128.     while (a->next && b) {
  129.         int cmp = position_cmp(&a->next, &b);
  130.         if (cmp == 0) {
  131.             struct position *dup = a->next;
  132.             a->next = a->next->next;
  133.             b = b->next;
  134.             position_free(dup);
  135.         } else if (cmp < 0) {
  136.             a = a->next;
  137.         } else if (cmp > 0) {
  138.             b = b->next;
  139.         }
  140.     }
  141.     return head.next;
  142. }
  143.  
  144. struct position *selection(const char *code)
  145. {
  146.     struct position *head = NULL, *start = NULL;
  147.     while (*code) {
  148.         struct position *next = position_parse(&code);
  149.         switch (*code) {
  150.         case ':':
  151.             code++;
  152.             start = next;
  153.             break;
  154.         case '&':
  155.             code++;  // fallthrough
  156.         case '~':
  157.         case '\0':
  158.             if (start) {
  159.                 next->next = head;
  160.                 head = selection_range(start, next);
  161.                 start = NULL;
  162.             } else {
  163.                 next->next = head;
  164.                 head = next;
  165.             }
  166.             break;
  167.         }
  168.         if (*code == '~') {
  169.             struct position *diff = selection(++code);
  170.             head = selection_diff(selection_uniq(head), diff);
  171.             selection_free(diff);
  172.             return head;
  173.         }
  174.     }
  175.     return selection_uniq(head);
  176. }
  177.  
  178. void selection_print(const struct position *s)
  179. {
  180.     putchar('(');
  181.     for (; s; s = s->next) {
  182.         printf("[%d %d]%s", s->col, s->row, s->next ? " " : "");
  183.     }
  184.     putchar(')');
  185. }
  186.  
  187. int main(int argc, char **argv)
  188. {
  189.     struct position *s = selection(argc > 1 ? argv[1] : "");
  190.     printf("%zu\n", selection_size(s));
  191.     for (struct position * p = s; p; p = p->next)
  192.         printf("%d, %d\n", p->col, p->row);
  193.     selection_free(s);
  194.     return 0;
  195. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement