Advertisement
Guest User

Living Anagrams

a guest
Oct 27th, 2014
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 20.36 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5.  
  6. #define FCLOSE(fd) fclose(fd), fd = NULL
  7. #define FREE(p) free(p), p = NULL
  8.  
  9. #define CHUNK_SIZE 65536
  10.  
  11. #define Agrave -64
  12. #define Aacute -63
  13. #define Acirc -62
  14. #define Atilde -61
  15. #define Auml -60
  16. #define Ccedil -57
  17. #define Egrave -56
  18. #define Eacute -55
  19. #define Ecirc -54
  20. #define Euml -53
  21. #define Igrave -52
  22. #define Iacute -51
  23. #define Icirc -50
  24. #define Iuml -49
  25. #define Ntilde -47
  26. #define Ograve -46
  27. #define Oacute -45
  28. #define Ocirc -44
  29. #define Otilde -43
  30. #define Ouml -42
  31. #define Ugrave -39
  32. #define Uacute -38
  33. #define Ucirc -37
  34. #define Uuml -36
  35. #define Yacute -35
  36. #define agrave -32
  37. #define aacute -31
  38. #define acirc -30
  39. #define atilde -29
  40. #define auml -28
  41. #define ccedil -25
  42. #define egrave -24
  43. #define eacute -23
  44. #define ecirc -22
  45. #define euml -21
  46. #define igrave -20
  47. #define iacute -19
  48. #define icirc -18
  49. #define iuml -17
  50. #define ntilde -15
  51. #define ograve -14
  52. #define oacute -13
  53. #define ocirc -12
  54. #define otilde -11
  55. #define ouml -10
  56. #define ugrave -7
  57. #define uacute -6
  58. #define ucirc -5
  59. #define uuml -4
  60. #define yacute -3
  61.  
  62. #define HASH_INIT 5381
  63. #define HASH_SHIFT 5
  64.  
  65. #define REQ_PATH "p"
  66. #define REQ_VIEW "v"
  67. #define REQ_QUIT "q"
  68.  
  69. typedef struct dictionary_s dictionary_t;
  70. struct dictionary_s {
  71.     size_t nwords;
  72.     char **words;
  73. };
  74.  
  75. typedef struct anagram_s anagram_t;
  76. struct anagram_s {
  77.     size_t szkey;
  78.     char *key;
  79.     dictionary_t list;
  80.     size_t nlinks;
  81.     anagram_t **links;
  82.     int marked;
  83.     anagram_t *ancestor;
  84.     anagram_t *next;
  85. };
  86.  
  87. typedef struct hanagrams_s hanagrams_t;
  88. struct hanagrams_s {
  89.     size_t nanagrams;
  90.     anagram_t **anagrams;
  91. };
  92.  
  93. void log_error(const char *, ...);
  94. size_t line_size(char *);
  95. int compare_chars(const void *, const void *);
  96. size_t hash_key(size_t, const char *, size_t);
  97. size_t word_index(const dictionary_t *, const char *);
  98. anagram_t *get_anagram(size_t, const char *, const hanagrams_t *);
  99. void dictionary_cleanup(dictionary_t *);
  100. void anagram_cleanup(anagram_t *);
  101. void hanagrams_cleanup(hanagrams_t *);
  102. void set_char(char *, size_t *, char);
  103. int line_to_word(size_t, const char *, size_t, char *);
  104. void read_dictionary_cleanup(char *, FILE *);
  105. dictionary_t *read_dictionary(const char *);
  106. size_t next_prime(size_t);
  107. anagram_t *get_anagram_and_hash(size_t, const char *, const hanagrams_t *, size_t *);
  108. int add_word_to_list(dictionary_t *, char *);
  109. void delete_char(size_t *, char *, size_t);
  110. size_t insert_index(size_t, const char *, size_t, char);
  111. void insert_char(size_t *, char *, size_t, char);
  112. int add_link(anagram_t *, anagram_t *);
  113. int test_anagram(anagram_t *, const hanagrams_t *);
  114. size_t insert_char_loop(char, char, size_t, anagram_t *, const hanagrams_t *);
  115. int dr_links(anagram_t *, size_t, const hanagrams_t *);
  116. anagram_t *create_anagram(size_t, char *, char *, anagram_t *, const hanagrams_t *);
  117. hanagrams_t *create_hanagrams(const dictionary_t *);
  118. size_t read_separators(size_t, const char *, size_t);
  119. size_t read_letters(size_t, const char *, size_t);
  120. anagram_t *get_anagram_from_word(size_t, const char *, const hanagrams_t *);
  121. void print_path(const anagram_t *, const anagram_t *);
  122. void search_path(const char *, anagram_t *, const char *, anagram_t *);
  123. void view_anagram(const anagram_t *);
  124. int process_requests(const hanagrams_t *);
  125.  
  126. void log_error(const char *format, ...) {
  127. va_list args;
  128.     va_start(args, format);
  129.     vfprintf(stderr, format, args);
  130.     va_end(args);
  131. }
  132.  
  133. size_t line_size(char *line) {
  134. size_t size = strlen(line);
  135.     if (line[size-1] == '\n') {
  136.         line[size-1] = 0;
  137.         size--;
  138.     }
  139.     return size;
  140. }
  141.  
  142. int compare_chars(const void *a, const void *b) {
  143. const char *pa = a, *pb = b;
  144.     return *pa-*pb;
  145. }
  146.  
  147. size_t hash_key(size_t szkey, const char *key, size_t nanagrams) {
  148. size_t hash = HASH_INIT, i;
  149.     for (i = 0; i < szkey; i++) hash += (hash << HASH_SHIFT)+(unsigned char)key[i];
  150.     return hash%nanagrams;
  151. }
  152.  
  153. size_t word_index(const dictionary_t *list, const char *word) {
  154. size_t i;
  155.     for (i = 0; i < list->nwords && strcmp(list->words[i], word); i++);
  156.     return i;
  157. }
  158.  
  159. anagram_t *get_anagram(size_t szkey, const char *key, const hanagrams_t *hanagrams) {
  160. anagram_t *anagram = NULL;
  161.     for (anagram = hanagrams->anagrams[hash_key(szkey, key, hanagrams->nanagrams)]; anagram && strcmp(anagram->key, key); anagram = anagram->next);
  162.     return anagram;
  163. }
  164.  
  165. void dictionary_cleanup(dictionary_t *dictionary) {
  166. size_t i;
  167.     if (dictionary) {
  168.         if (dictionary->words) {
  169.             for (i = 0; i < dictionary->nwords; i++) FREE(dictionary->words[i]);
  170.             FREE(dictionary->words);
  171.         }
  172.         FREE(dictionary);
  173.     }
  174. }
  175.  
  176. void anagram_cleanup(anagram_t *anagram) {
  177. anagram_t *tmpanagram;
  178.     while (anagram) {
  179.         if (anagram->links) FREE(anagram->links);
  180.         if (anagram->list.words) FREE(anagram->list.words);
  181.         FREE(anagram->key);
  182.         tmpanagram = anagram->next;
  183.         FREE(anagram);
  184.         anagram = tmpanagram;
  185.     }
  186. }
  187.  
  188. void hanagrams_cleanup(hanagrams_t *hanagrams) {
  189. size_t i;
  190.     if (hanagrams) {
  191.         if (hanagrams->anagrams) {
  192.             for (i = 0; i < hanagrams->nanagrams; i++) anagram_cleanup(hanagrams->anagrams[i]);
  193.             FREE(hanagrams->anagrams);
  194.         }
  195.         FREE(hanagrams);
  196.     }
  197. }
  198.  
  199. void set_char(char *word, size_t *ind, char chr) {
  200.     word[*ind] = chr;
  201.     (*ind)++;
  202. }
  203.  
  204. int line_to_word(size_t szline, const char *line, size_t nwords, char *word) {
  205. int r = 1;
  206. size_t i, j = 0;
  207.     for (i = 0; i < szline && r; i++) {
  208.         if (line[i] >= 'A' && line[i] <= 'Z') set_char(word, &j, line[i]);
  209.         else if (line[i] >= 'a' && line[i] <= 'z') set_char(word, &j, (char)(line[i]-' '));
  210.         else {
  211.             switch (line[i]) {
  212.             case Agrave:
  213.             case Aacute:
  214.             case Acirc:
  215.             case Atilde:
  216.             case Auml:
  217.             case agrave:
  218.             case aacute:
  219.             case acirc:
  220.             case atilde:
  221.             case auml:
  222.                 set_char(word, &j, 'A');
  223.                 break;
  224.             case Ccedil:
  225.             case ccedil:
  226.                 set_char(word, &j, 'C');
  227.                 break;
  228.             case Egrave:
  229.             case Eacute:
  230.             case Ecirc:
  231.             case Euml:
  232.             case egrave:
  233.             case eacute:
  234.             case ecirc:
  235.             case euml:
  236.                 set_char(word, &j, 'E');
  237.                 break;
  238.             case Igrave:
  239.             case Iacute:
  240.             case Icirc:
  241.             case Iuml:
  242.             case igrave:
  243.             case iacute:
  244.             case icirc:
  245.             case iuml:
  246.                 set_char(word, &j, 'I');
  247.                 break;
  248.             case Ograve:
  249.             case Oacute:
  250.             case Ocirc:
  251.             case Otilde:
  252.             case Ouml:
  253.             case ograve:
  254.             case oacute:
  255.             case ocirc:
  256.             case otilde:
  257.             case ouml:
  258.                 set_char(word, &j, 'O');
  259.                 break;
  260.             case Ugrave:
  261.             case Uacute:
  262.             case Ucirc:
  263.             case Uuml:
  264.             case ugrave:
  265.             case uacute:
  266.             case ucirc:
  267.             case uuml:
  268.                 set_char(word, &j, 'U');
  269.                 break;
  270.             case Yacute:
  271.             case yacute:
  272.                 set_char(word, &j, 'Y');
  273.                 break;
  274.             case '-':
  275.                 break;
  276.             default:
  277.                 r = 0;
  278.                 break;
  279.             }
  280.         }
  281.     }
  282.     if (r) word[j] = 0;
  283.     else log_error("line_to_word: line %u invalid character 0x%02x\n", nwords+1, line[i]);
  284.     return r;
  285. }
  286.  
  287. void read_dictionary_cleanup(char *line, FILE *fd) {
  288.     if (fd) FCLOSE(fd);
  289.     if (line) FREE(line);
  290. }
  291.  
  292. dictionary_t *read_dictionary(const char *filename) {
  293. char *line = NULL, *tmpline = NULL, **tmpwords = NULL;
  294. size_t maxnwords, maxszline, szline;
  295. FILE *fd = NULL;
  296. dictionary_t *dictionary = NULL;
  297.     if (!(dictionary = malloc(sizeof(dictionary_t)))) {
  298.         log_error("read_dictionary: malloc error (dictionary)\n");
  299.         return NULL;
  300.     }
  301.     maxnwords = CHUNK_SIZE;
  302.     if (!(dictionary->words = malloc(sizeof(char *)*maxnwords))) {
  303.         log_error("read_dictionary: malloc error (dictionary->words)\n");
  304.         dictionary_cleanup(dictionary);
  305.         return NULL;
  306.     }
  307.     dictionary->nwords = 0;
  308.     maxszline = CHUNK_SIZE;
  309.     if (!(line = malloc(sizeof(char)*(maxszline+1)))) {
  310.         log_error("read_dictionary: malloc error (line)\n");
  311.         read_dictionary_cleanup(line, fd);
  312.         dictionary_cleanup(dictionary);
  313.         return NULL;
  314.     }
  315.     if (!(fd = fopen(filename, "r"))) {
  316.         log_error("read_dictionary: cannot open file %s\n", filename);
  317.         read_dictionary_cleanup(line, fd);
  318.         dictionary_cleanup(dictionary);
  319.         return NULL;
  320.     }
  321.     while (fgets(line, (int)maxszline+1, fd)) {
  322.         while ((szline = line_size(line)) == maxszline) {
  323.             maxszline += CHUNK_SIZE;
  324.             if (!(tmpline = realloc(line, sizeof(char)*(maxszline+1)))) {
  325.                 log_error("read_dictionary: realloc error (line)\n");
  326.                 read_dictionary_cleanup(line, fd);
  327.                 dictionary_cleanup(dictionary);
  328.                 return NULL;
  329.             }
  330.             line = tmpline;
  331.             fgets(&line[maxszline-CHUNK_SIZE], CHUNK_SIZE+1, fd);
  332.         }
  333.         if (dictionary->nwords == maxnwords) {
  334.             maxnwords += CHUNK_SIZE;
  335.             if (!(tmpwords = realloc(dictionary->words, sizeof(char *)*maxnwords))) {
  336.                 log_error("read_dictionary: realloc error (dictionary->words)\n");
  337.                 read_dictionary_cleanup(line, fd);
  338.                 dictionary_cleanup(dictionary);
  339.                 return NULL;
  340.             }
  341.             dictionary->words = tmpwords;
  342.         }
  343.         if (!(dictionary->words[dictionary->nwords] = malloc(sizeof(char)*(szline+1)))) {
  344.             log_error("read_dictionary: malloc error (dictionary->words[%u])\n", dictionary->nwords);
  345.             read_dictionary_cleanup(line, fd);
  346.             dictionary_cleanup(dictionary);
  347.             return NULL;
  348.         }
  349.         if (!line_to_word(szline, line, dictionary->nwords, dictionary->words[dictionary->nwords])) {
  350.             read_dictionary_cleanup(line, fd);
  351.             dictionary_cleanup(dictionary);
  352.             return NULL;
  353.         }
  354.         dictionary->nwords++;
  355.     }
  356.     read_dictionary_cleanup(line, fd);
  357.     return dictionary;
  358. }
  359.  
  360. size_t next_prime(size_t v) {
  361. size_t p = v | 1, i;
  362.     do {
  363.         for (i = 3; i*i <= p && p%i; i += 2);
  364.         if (i*i <= p) p += 2;
  365.     }
  366.     while (i*i <= p);
  367.     return p;
  368. }
  369.  
  370. anagram_t *get_anagram_and_hash(size_t szkey, const char *key, const hanagrams_t *hanagrams, size_t *hash) {
  371. anagram_t *anagram = NULL;
  372.     for (anagram = hanagrams->anagrams[(*hash = hash_key(szkey, key, hanagrams->nanagrams))]; anagram && strcmp(anagram->key, key); anagram = anagram->next);
  373.     return anagram;
  374. }
  375.  
  376. int add_word_to_list(dictionary_t *list, char *word) {
  377. char **tmpwords = NULL;
  378.     if (word_index(list, word) == list->nwords) {
  379.         list->nwords++;
  380.         if (!(tmpwords = realloc(list->words, sizeof(char *)*list->nwords))) {
  381.             log_error("add_word_to_list: realloc error (list->words)\n");
  382.             return 0;
  383.         }
  384.         list->words = tmpwords;
  385.         list->words[list->nwords-1] = word;
  386.     }
  387.     return 1;
  388. }
  389.  
  390. void delete_char(size_t *szkey, char *key, size_t ind) {
  391. size_t i;
  392.     for (i = ind; i < *szkey; i++) key[i] = key[i+1];
  393.     (*szkey)--;
  394. }
  395.  
  396. size_t insert_index(size_t szkey, const char *key, size_t ind, char c) {
  397.     while (ind < szkey && key[ind] < c) ind++;
  398.     return ind;
  399. }
  400.  
  401. void insert_char(size_t *szkey, char *key, size_t ind, char c) {
  402. size_t i;
  403.     for (i = *szkey+1; i > ind; i--) key[i] = key[i-1];
  404.     key[ind] = c;
  405.     (*szkey)++;
  406. }
  407.  
  408. int add_link(anagram_t *anagram, anagram_t *add) {
  409. anagram_t **tmplinks = NULL;
  410.     anagram->nlinks++;
  411.     if (anagram->nlinks > 1) {
  412.         if (!(tmplinks = realloc(anagram->links, sizeof(anagram_t *)*anagram->nlinks))) {
  413.             log_error("add_link: realloc error (anagram->links)\n");
  414.             return 0;
  415.         }
  416.         anagram->links = tmplinks;
  417.     }
  418.     else {
  419.         if (!(anagram->links = malloc(sizeof(anagram_t *)))) {
  420.             log_error("add_link: malloc error (anagram->links)\n");
  421.             return 0;
  422.         }
  423.     }
  424.     anagram->links[anagram->nlinks-1] = add;
  425.     return 1;
  426. }
  427.  
  428. int test_anagram(anagram_t *anagram, const hanagrams_t *hanagrams) {
  429. anagram_t *test = NULL;
  430.     if ((test = get_anagram(anagram->szkey, anagram->key, hanagrams))) {
  431.         if (!add_link(anagram, test)) return 0;
  432.         if (!add_link(test, anagram)) return 0;
  433.     }
  434.     return 1;
  435. }
  436.  
  437. size_t insert_char_loop(char c1, char c2, size_t ind, anagram_t *anagram, const hanagrams_t *hanagrams) {
  438. char c;
  439.     for (c = c1; c <= c2; c++) {
  440.         ind = insert_index(anagram->szkey, anagram->key, ind, c);
  441.         insert_char(&anagram->szkey, anagram->key, ind, c);
  442.         if (!test_anagram(anagram, hanagrams)) return 0;
  443.         delete_char(&anagram->szkey, anagram->key, ind);
  444.     }
  445.     return ind;
  446. }
  447.  
  448. int dr_links(anagram_t *anagram, size_t ind, const hanagrams_t *hanagrams) {
  449. char c;
  450.     c = anagram->key[ind];
  451.     delete_char(&anagram->szkey, anagram->key, ind);
  452.     if (!test_anagram(anagram, hanagrams)) return 0;
  453.     insert_char_loop((char)(c+1), 'Z', insert_char_loop('A', (char)(c-1), 0, anagram, hanagrams), anagram, hanagrams);
  454.     insert_char(&anagram->szkey, anagram->key, ind, c);
  455.     return 1;
  456. }
  457.  
  458. anagram_t *create_anagram(size_t szkey, char *key, char *word, anagram_t *next, const hanagrams_t *hanagrams) {
  459. size_t i;
  460. anagram_t *anagram = NULL;
  461.     if (!(anagram = malloc(sizeof(anagram_t)))) {
  462.         log_error("create_anagram: malloc error (anagram)\n");
  463.         return NULL;
  464.     }
  465.     anagram->szkey = szkey;
  466.     anagram->key = key;
  467.     anagram->list.words = NULL;
  468.     anagram->links = NULL;
  469.     anagram->list.nwords = 1;
  470.     if (!(anagram->list.words = malloc(sizeof(char *)))) {
  471.         log_error("create_anagram: malloc error (anagram->list.words)\n");
  472.         anagram_cleanup(anagram);
  473.         return NULL;
  474.     }
  475.     anagram->list.words[0] = word;
  476.     anagram->nlinks = 0;
  477.     if (!dr_links(anagram, 0, hanagrams)) {
  478.         anagram_cleanup(anagram);
  479.         return NULL;
  480.     }
  481.     for (i = 1; i < szkey; i++) {
  482.         if (key[i] > key[i-1]) {
  483.             if (!dr_links(anagram, i, hanagrams)) {
  484.                 anagram_cleanup(anagram);
  485.                 return NULL;
  486.             }
  487.         }
  488.     }
  489.     insert_char_loop('A', 'Z', 0, anagram, hanagrams);
  490.     anagram->marked = 0;
  491.     anagram->ancestor = NULL;
  492.     anagram->next = next;
  493.     return anagram;
  494. }
  495.  
  496. hanagrams_t *create_hanagrams(const dictionary_t *dictionary) {
  497. char *key = NULL;
  498. size_t szword, hash, i;
  499. anagram_t *anagram = NULL;
  500. hanagrams_t *hanagrams = NULL;
  501.     if (!(hanagrams = malloc(sizeof(hanagrams_t)))) {
  502.         log_error("create_hanagrams: malloc error (hanagrams)\n");
  503.         return NULL;
  504.     }
  505.     hanagrams->nanagrams = next_prime(dictionary->nwords);
  506.     if (!(hanagrams->anagrams = malloc(sizeof(anagram_t *)*hanagrams->nanagrams))) {
  507.         log_error("create_hanagrams: malloc error (hanagrams->anagrams)\n");
  508.         hanagrams_cleanup(hanagrams);
  509.         return NULL;
  510.     }
  511.     for (i = 0; i < hanagrams->nanagrams; i++) hanagrams->anagrams[i] = NULL;
  512.     for (i = 0; i < dictionary->nwords; i++) {
  513.         szword = strlen(dictionary->words[i]);
  514.         if (!(key = malloc(sizeof(char)*(szword+2)))) {
  515.             log_error("create_hanagrams: malloc error (key)\n");
  516.             hanagrams_cleanup(hanagrams);
  517.             return NULL;
  518.         }
  519.         strcpy(key, dictionary->words[i]);
  520.         qsort(key, szword, sizeof(char), compare_chars);
  521.         if ((anagram = get_anagram_and_hash(szword, key, hanagrams, &hash))) {
  522.             FREE(key);
  523.             if (!add_word_to_list(&anagram->list, dictionary->words[i])) {
  524.                 hanagrams_cleanup(hanagrams);
  525.                 return NULL;
  526.             }
  527.         }
  528.         else {
  529.             if (!(hanagrams->anagrams[hash] = create_anagram(szword, key, dictionary->words[i], hanagrams->anagrams[hash], hanagrams))) {
  530.                 FREE(key);
  531.                 hanagrams_cleanup(hanagrams);
  532.                 return NULL;
  533.             }
  534.         }
  535.     }
  536.     return hanagrams;
  537. }
  538.  
  539. size_t read_separators(size_t szline, const char *line, size_t ind) {
  540.     while (ind < szline && (line[ind] == ' ' || line[ind] == '\t')) ind++;
  541.     return ind;
  542. }
  543.  
  544. size_t read_letters(size_t szline, const char *line, size_t ind) {
  545.     while (ind < szline && line[ind] >= 'A' && line[ind] <= 'Z') ind++;
  546.     return ind;
  547. }
  548.  
  549. anagram_t *get_anagram_from_word(size_t szword, const char *word, const hanagrams_t *hanagrams) {
  550. char *key = NULL;
  551. anagram_t *anagram = NULL;
  552.     if (!(key = malloc(sizeof(char)*(szword+1)))) {
  553.         log_error("get_anagram_from_word: malloc error (key)\n");
  554.         return NULL;
  555.     }
  556.     strcpy(key, word);
  557.     qsort(key, szword, sizeof(char), compare_chars);
  558.     if ((anagram = get_anagram(szword, key, hanagrams))) {
  559.         FREE(key);
  560.         if (word_index(&anagram->list, word) < anagram->list.nwords) return anagram;
  561.         else {
  562.             log_error("get_anagram_from_word: word %s not found\n", word);
  563.             return NULL;
  564.         }
  565.     }
  566.     else {
  567.         log_error("get_anagram_from_word: key %s not found\n", key);
  568.         FREE(key);
  569.         return NULL;
  570.     }
  571. }
  572.  
  573. void print_path(const anagram_t *anagram, const anagram_t *first) {
  574.     if (anagram != first) {
  575.         print_path(anagram->ancestor, first);
  576.         fprintf(stdout, " %s", anagram->list.words[0]);
  577.     }
  578. }
  579.  
  580. void search_path(const char *word1, anagram_t *anagram1, const char *word2, anagram_t *anagram2) {
  581. size_t maxszqueue, szqueue, i, j;
  582. anagram_t **queue = NULL, **tmpqueue = NULL;
  583.     maxszqueue = CHUNK_SIZE;
  584.     if (!(queue = malloc(sizeof(anagram_t *)*maxszqueue))) {
  585.         log_error("search_path: malloc error (queue)\n");
  586.         return;
  587.     }
  588.     szqueue = 1;
  589.     queue[0] = anagram1;
  590.     queue[0]->marked = 1;
  591.     for (i = 0; i < szqueue && queue[i] != anagram2; i++) {
  592.         for (j = 0; j < queue[i]->nlinks; j++) {
  593.             if (!queue[i]->links[j]->marked) {
  594.                 if (szqueue == maxszqueue) {
  595.                     maxszqueue += CHUNK_SIZE;
  596.                     if (!(tmpqueue = realloc(queue, sizeof(anagram_t *)*maxszqueue))) {
  597.                         log_error("search_path: realloc error (queue)\n");
  598.                         FREE(queue);
  599.                         return;
  600.                     }
  601.                     queue = tmpqueue;
  602.                 }
  603.                 queue[szqueue] = queue[i]->links[j];
  604.                 queue[szqueue]->marked = 1;
  605.                 queue[szqueue]->ancestor = queue[i];
  606.                 szqueue++;
  607.             }
  608.         }
  609.     }
  610.     if (anagram1 != anagram2 && i < szqueue) {
  611.         fprintf(stdout, "Path %s", word1);
  612.         print_path(anagram2->ancestor, anagram1);
  613.         fprintf(stdout, " %s\n", word2);
  614.         fflush(stdout);
  615.     }
  616.     else log_error("No path found between %s and %s\n", word1, word2);
  617.     queue[0]->marked = 0;
  618.     for (i = 1; i < szqueue; i++) {
  619.         queue[i]->marked = 0;
  620.         queue[i]->ancestor = NULL;
  621.     }
  622.     FREE(queue);
  623. }
  624.  
  625. void view_anagram(const anagram_t *anagram) {
  626. size_t i;
  627.     fprintf(stdout, "Size %u\n", anagram->szkey);
  628.     fprintf(stdout, "Key %s\n", anagram->key);
  629.     fprintf(stdout, "Words (%u)", anagram->list.nwords);
  630.     for (i = 0; i < anagram->list.nwords; i++) fprintf(stdout, " %s", anagram->list.words[i]);
  631.     fprintf(stdout, "\n");
  632.     fprintf(stdout, "Links (%u)", anagram->nlinks);
  633.     for (i = 0; i < anagram->nlinks; i++) fprintf(stdout, " %s", anagram->links[i]->key);
  634.     fprintf(stdout, "\n");
  635.     fflush(stdout);
  636. }
  637.  
  638. int process_requests(const hanagrams_t *hanagrams) {
  639. char *line = NULL, *tmpline = NULL, *word1 = NULL, *word2 = NULL;
  640. int r;
  641. size_t maxszline, szline, indword11, indword12, indword21, indword22;
  642. anagram_t *anagram1 = NULL, *anagram2 = NULL;
  643.     maxszline = CHUNK_SIZE;
  644.     if (!(line = malloc(sizeof(char)*(maxszline+1)))) {
  645.         log_error("process_requests: malloc error (line)\n");
  646.         return 0;
  647.     }
  648.     do {
  649.         fprintf(stdout, "? ");
  650.         fflush(stdout);
  651.         if (fgets(line, (int)maxszline+1, stdin)) {
  652.             while ((szline = line_size(line)) == maxszline) {
  653.                 maxszline += CHUNK_SIZE;
  654.                 if (!(tmpline = realloc(line, sizeof(char)*(maxszline+1)))) {
  655.                     log_error("process_requests: realloc error (line)\n");
  656.                     FREE(line);
  657.                     return 0;
  658.                 }
  659.                 line = tmpline;
  660.                 fgets(&line[maxszline-CHUNK_SIZE], CHUNK_SIZE+1, stdin);
  661.             }
  662.             if (!strncmp(line, REQ_PATH, strlen(REQ_PATH))) {
  663.                 indword11 = read_separators(szline, line, 1);
  664.                 indword12 = read_letters(szline, line, indword11);
  665.                 indword21 = read_separators(szline, line, indword12);
  666.                 indword22 = read_letters(szline, line, indword21);
  667.                 if (1 < indword11 && indword11 < indword12 && indword12 < indword21 && indword21 < indword22 && indword22 == szline) {
  668.                     word1 = &line[indword11];
  669.                     line[indword12] = 0;
  670.                     word2 = &line[indword21];
  671.                     if ((anagram1 = get_anagram_from_word(indword12-indword11, word1, hanagrams)) && (anagram2 = get_anagram_from_word(indword22-indword21, word2, hanagrams))) search_path(word1, anagram1, word2, anagram2);
  672.                 }
  673.                 else log_error("process_requests: syntax error in path request\n");
  674.                 r = 1;
  675.             }
  676.             else if (!strncmp(line, REQ_VIEW, strlen(REQ_VIEW))) {
  677.                 indword11 = read_separators(szline, line, 1);
  678.                 indword12 = read_letters(szline, line, indword11);
  679.                 if (1 < indword11 && indword11 < indword12 && indword12 == szline) {
  680.                     if ((anagram1 = get_anagram_from_word(indword12-indword11, &line[indword11], hanagrams))) view_anagram(anagram1);
  681.                 }
  682.                 else log_error("process_requests: syntax error in view request\n");
  683.                 r = 1;
  684.             }
  685.             else if (!strcmp(line, REQ_QUIT)) r = 2;
  686.             else {
  687.                 log_error("process_requests: unknown request\n");
  688.                 r = 1;
  689.             }
  690.         }
  691.         else {
  692.             log_error("process_requests: fgets error\n");
  693.             FREE(line);
  694.             return 0;
  695.         }
  696.     }
  697.     while (r == 1);
  698.     FREE(line);
  699.     return r;
  700. }
  701.  
  702. int main(int argc, char **argv) {
  703. int r;
  704. dictionary_t *dictionary = NULL;
  705. hanagrams_t *hanagrams = NULL;
  706.     if (argc != 2) {
  707.         log_error("Usage: %s file\n", argv[0]);
  708.         return EXIT_FAILURE;
  709.     }
  710.     if (!(dictionary = read_dictionary(argv[1]))) return EXIT_FAILURE;
  711.     if (!(hanagrams = create_hanagrams(dictionary))) {
  712.         dictionary_cleanup(dictionary);
  713.         return EXIT_FAILURE;
  714.     }
  715.     r = process_requests(hanagrams);
  716.     hanagrams_cleanup(hanagrams);
  717.     dictionary_cleanup(dictionary);
  718.     return r ? EXIT_SUCCESS:EXIT_FAILURE;
  719. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement