#include #include #include #include #include #include #include #include #include #define DICTIONARY "/usr/share/dict/words" struct trie { struct trie *children[26]; uint8_t terminal; }; void new_trie(struct trie *tree) { uint8_t idx = 0; for(; idx < 26; idx += 1) { tree->children[idx] = NULL; } tree->terminal = 0; } void trie_insert(struct trie *tree, const char *str, uint8_t len) { struct trie *node = tree; uint8_t idx = 0; for(; idx < len; idx += 1) { uint8_t pos = tolower(str[idx]) - 'a'; if(node->children[pos] == NULL) { void *mem = malloc(sizeof(struct trie)); if(mem == NULL) { fprintf(stderr, "could not allocate memory: %s\n", strerror(errno)); exit(1); } node->children[pos] = mem; new_trie(node->children[pos]); } node = node->children[pos]; } node->terminal = 1; } uint8_t trie_has(struct trie *tree, const char *str, uint8_t len) { struct trie *node = tree; uint8_t idx = 0; for(; idx < len; idx += 1) { uint8_t pos = tolower(str[idx]) - 'a'; if(node->children[pos] == NULL) { return 0; } node = node->children[pos]; } return node->terminal; } int main(int argc, char **argv) { struct trie dict; new_trie(&dict); int fd = open(DICTIONARY, O_RDONLY); if(fd < 0) { fprintf(stderr, "could not open %s: %s\n", DICTIONARY, strerror(errno)); return 1; } ssize_t bytes = 0; char buf[1024] = { 0 }; char word[128] = { 0 }; uint8_t len = 0; while((bytes = read(fd, buf, sizeof(buf))) > 0) { ssize_t idx = 0; for(; idx < bytes; idx += 1) { if(buf[idx] == '\n') { trie_insert(&dict, word, len); len = 0; bzero(word, sizeof(word)); } else if(len < sizeof(word)) { word[len] = buf[idx]; len += 1; } } } if(bytes < 0) { fprintf(stderr, "could not read from %s: %s\n", DICTIONARY, strerror(errno)); return 1; } const char *check = "paladin"; if(argc > 1) { check = argv[1]; } return !trie_has(&dict, check, strlen(check)); }