Task: Alternade words

C: #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#define WORD_BUF_SIZE 30
#define MIN_WORD_SIZE 6


void fail(void) {
    fprintf(stderr, "%s\n", strerror(errno));
    exit(42);
}


struct trie_node {
    char ch, final;
    struct trie_node *parent, *sibling, *root, *child; 
};

struct trie_node *alloc_node() {
    struct trie_node *t = calloc(1, sizeof(struct trie_node));
    if (t == NULL) fail();
    return t;
}

struct trie_node *make_sibling(struct trie_node *node) {
    struct trie_node *t = alloc_node();
    node->sibling = t;
    t->ch = node->ch;
    t->parent = node->parent;
    t->root = node->root;
    return t;
}

struct trie_node *make_child(struct trie_node *node, char ch) {
    struct trie_node *t = alloc_node();
    t->parent = node;
    t->ch = ch;
    t->root = node->root;
    node->child = t;
    return t;
}


struct trie_node *add_word(struct trie_node *root, const char *word) {
    struct trie_node *cur = root;
    for (; *word; word++) {
        while (cur->child == NULL || cur->child->ch != *word) {
            if (cur->child == NULL) {
                
                make_child(cur, *word);
            } else {
                
                if (cur->sibling == NULL) make_sibling(cur);
                cur = cur->sibling;
            }
        }
        
        
        cur = cur->child;
    }
    cur->final = 1; 
    return cur;
}


struct trie_node *find_word(struct trie_node *root, const char *word) {
    struct trie_node *cur = root;
    for (; *word && cur; word++) {
        while (cur != NULL && cur->child != NULL && cur->child->ch != *word) {
            cur = cur->sibling;
        }
        if (cur == NULL) return NULL; 
        cur = cur->child;
    }
    if (cur && cur->final) return cur;
    else return NULL;
}


void scan_trie(struct trie_node *node, void callback(struct trie_node *)) {
    if (node == NULL) return;
    if (node->final) callback(node);
    scan_trie(node->child, callback);
    scan_trie(node->sibling, callback);
}


char *get_word(struct trie_node *node, char *buffer) {
    char t, *ch = buffer, *s = buffer;
    for (; node != NULL; node=node->parent) *ch++ = node->ch;
    for (ch-=2; ch >= s; ch--, s++) *ch ^= *s ^= *ch ^= *s;
    return buffer;
}


void check_alternade(struct trie_node *node) {
    static char word[WORD_BUF_SIZE], even[WORD_BUF_SIZE], odd[WORD_BUF_SIZE];
    char *p_even = even, *p_odd = odd;
    int i;
    
    
    if (strlen(get_word(node, word)) < MIN_WORD_SIZE) return;
    
    
    for (i=0; word[i]; i++) {
        if (i & 1) *p_odd++ = word[i];
        else *p_even++ = word[i];
    }
    *p_odd = *p_even = '\0';
        
    
    if (find_word(node->root, even) && find_word(node->root, odd)) {
        printf("%-20s%-10s%-10s\n", word, even, odd);
    }
}
          
int main(void) {
    struct trie_node *root = alloc_node();
    root->root = root;
    char word[WORD_BUF_SIZE], *nl;
    
    
    while (!feof(stdin)) {
        fgets(word, WORD_BUF_SIZE, stdin);
        if (nl = strchr(word, '\n')) *nl = '\0';  
        add_word(root, word);
    }
    
    
    scan_trie(root, check_alternade);
    return 0;
}







Python: WORDFILE = 'unixdict.txt'
MINLEN = 6

class Trie(object):
    
    class Node(object):
        
        def __init__(self, char='\0', parent=None):
            self.children = {}
            self.char = char
            self.final = False
            self.parent = parent
            
        def descend(self, char, extend=False):
            
            if not char in self.children:
                if not extend: return None
                self.children[char] = Trie.Node(char,self)
            return self.children[char]
        
    def __init__(self):
        self.root = Trie.Node()
    
    def insert(self, word):
        
        node = self.root
        for char in word: node = node.descend(char, extend=True)
        node.final = True
        return node
    
    def __contains__(self, word):
        
        node = self.root
        for char in word:
            node = node.descend(char)
            if not node: return False
        return node.final 
    
    def words(self):
        
        nodes = [self.root]
        while nodes:
            node = nodes.pop()
            nodes += node.children.values()
            if node.final:
                word = []
                while node:
                    if node.char != '\0': word.append(node.char)
                    node = node.parent
                yield "".join(reversed(word))
    
    def __iter__(self):
        return self.words()
                

words = Trie()
with open(WORDFILE, "rt") as f:
    for word in f.readlines():
        words.insert(word.strip())

for word in words:
    if len(word) < MINLEN: continue
    even = word[::2]
    odd = word[1::2]
    if even in words and odd in words:
        print(word, even, odd)