typedef struct {
    long count;             /* ÃâÇö ºóµµ */
    int  chr;               /* ¹®ÀÚ */
    int  len;               /* ºÎÈ£¾îÀÇ ºñÆ®¼ö */
    unsigned char code[8];  /* ºÎÈ£¾î */
    int  info;              /* 0:󸮴ë, 1:Group ¼±µÎ,2:ó¸®ÇÊ */
} CELL;

#define CHAR_SIZE    256    /* ±âÈ£ Á¾·ù */

long enShannon(unsigned char *code, long clen, unsigned char *text, long tlen){
    int    i, j, k;
    long   c, len;
    long   max;
    CELL   *cell;
    int    cellsize;
    long   count[CHAR_SIZE+1];
    int    char2cell[CHAR_SIZE+1];
    static unsigned char bit0[8] = {~128,~64,~32,~16,~8,~4,~2,~1};
    static unsigned char bit1[8] = { 128, 64, 32, 16, 8, 4, 2, 1};
    CELL   *getCode();

    if (tlen <= 0 || clen <= 512) return -1L;

    /* °¢ ¹®ÀÚÀÇ ÃâÇö ºóµµ¸¦ °è»ê */
    for (i = 0; i < CHAR_SIZE; i++) count[i] = 0;
    for (c = 0; c < tlen; c++) count[text[c]]++;

    /* ÃÖ´ë ÃâÇö ºóµµÀÇ °ªÀÌ 2¹ÙÀÌÆ®¸¦ ³ÑÁö ¾Ê°Ô Á¶Á¤ÇÑ´Ù */
    for (i = 0, max = 0; i < CHAR_SIZE; i++)
        if (count[i] > max) max = count[i];
    if ((k = max/0x10000L) > 0)
        for (i = 0, k++; i < CHAR_SIZE; i++)
            if (count[i] > 0) {
                count[i] /= k;
                if (count[i] == 0) count[i] = 1;
            }

    /* °¢ ¹®ÀÚÀÇ ÃâÇö ºóµµ¸¦ Ãâ·Â */
    for (i = 0; i < CHAR_SIZE; i++) {
        *code++ = (count[i] >> 8) & 0xff;
        *code++ = count[i] & 0xff;
    }
    count[CHAR_SIZE] = 1;         /* EOF */

    /* ºÎÈ£¾î¸¦ ¾ò´Â´Ù */
    if ((cell = getCode(&cellsize, count)) == NULL) return -1L;

    /* ¹®ÀÚ¸¦ ºÎÈ£¾î¿Í ´ëÀÀ½ÃŲ´Ù */
    for (i = 0; i < cellsize; i++) char2cell[cell[i]. chr] = i;
           
    /* °¢ ¹®ÀÚ¸¦ encode */
    for (c = 0, i = 0, len = 512; ; c++) {
        k = (c == tlen) ?  256 : text[c];
        k = char2cell[k];
        
        /* ºÎÈ£¾î¸¦ Ãâ·Â */
        for (j = 0; j < cell[k]. len; j++) {
            if (cell[k]. code[j>>3] & bit1[j&7]) *code |= bit1[i];
            else                                *code &= bit0[i];
            if (++i == 8) {
                code++;
                if (++len > clen) {
                    free(cell);
                    return -1L;
                }
                i = 0;
            }
        }
        if (c == tlen) break;
    }
    free(cell);
    if (i > 0) len++;
    return (len > clen) ?  -1L : len;
}

long deShannon(unsigned char *text, long tlen,
               unsigned char *code, long clen)
{
    int  i, j, k;
    long c, len;
    CELL   *cell;
    int    cellsize;
    long   count[CHAR_SIZE+1];
#   define NODE_SIZE (2*CHAR_SIZE+2)
    struct { int chr, left, right; } node[NODE_SIZE];
    int    root, freeNode;
    static unsigned char bit1[8] = {128,64,32,16,8,4,2,1};
    CELL   *getCode();

    if (clen <= 512) return -1L;

    /* °¢ ¹®ÀÚÀÇ ÃâÇö ºóµµ¸¦ ¼¼Æ® */
    for (i = 0; i < CHAR_SIZE; i++) count[i] = 0;
    for (i = 0; i < 256; i++) {
        count[i] = *code++;
        count[i] = (count[i] << 8) | *code++;
    }
    
    /* EOF */
    count[256] = 1;

    /* ºÎÈ£¾î¸¦ ¾ò´Â´Ù */
    if ((cell = getCode(&cellsize, count)) == NULL) return -1L;

    /* ºÎÈ£¾î¿¡ ´ëÀÀÇÏ´Â ºÎÈ£³ª¹«¸¦ ¸¸µç´Ù */
    for (i = 0; i < NODE_SIZE; i++) {
        node[i]. chr = NODE_SIZE;
        node[i]. left = node[i]. right = 0;
    }
    root = 0; freeNode = 1;
    
    for (i = 0; i < cellsize; i++) {
        for (j = 0, k = root; j < cell[i]. len; j++) {
            if (cell[i]. code[j>>3] & bit1[j&7]) {
                if (node[k]. right == 0) node[k]. right = freeNode++;
                k = node[k]. right;
            } else {
                if (node[k]. left  == 0) node[k]. left  = freeNode++;
                k = node[k]. left;
            }
        }
        node[k]. chr = cell[i]. chr;
    }

    /* º¹È£È­ */
    for (i = 0, len = 0, c = 512; ; ) {
        /* ºÎÈ£¾î¿¡ ´ëÀÀÇÏ´Â ¹®ÀÚ ³ëµå¸¦ ¾ò´Â´Ù */
        k = root;
        do {
            k = (*code & bit1[i]) ?  node[k]. right : node[k]. left;
            if (++i == 8) {
                code++;
                if (++c > clen) return -1L;
                i = 0;
            }
        } while (node[k]. chr > CHAR_SIZE);
        if (node[k]. chr == CHAR_SIZE) break;
        if (++len > tlen) {
            free(cell);
            return -1L;
        }
        *text++ = node[k]. chr;
    }
    free(cell);
    return len;
}

/* ºÎÈ£¾î¸¦ ¾ò´Â´Ù */
static CELL *getCode(int *cellsize, long *count){
    int    i, j,  k;
    CELL   *cell;
    int    size;
    long   sum, half;
    int    left, mid, right;
    static unsigned char bit0[8] = {~128,~64,~32,~16,~8,~4,~2,~1};
    static unsigned char bit1[8] = { 128, 64, 32, 16, 8, 4, 2, 1};

    /* ±×·ì Å©±âÀÇ °áÁ¤ */
    for (i = 0, size = 0; i <= CHAR_SIZE; i++) if (count[i] > 0) size++;

    if ((cell = (CELL *) malloc(sizeof(CELL) *size)) == NULL) return NULL;

    /* ¹®ÀÚÀÇ ÃâÇö ºóµµ¸¦ ³»¸²Â÷¼ø¿¡ ¼ÒÆ® */
    for (i = 0, j = 0; i <= CHAR_SIZE; i++)
        if (count[i] > 0) {
            cell[j]. count = count[i];
            cell[j]. chr = i;
            cell[j]. len = 0;
            cell[j]. info = 0;
            j++;
        }
    for (i = 0; i < size - 1; i++) {
        k = i;
        for (j = i+1; j < size; j++)
            if (cell[j]. count > cell[k]. count) k = j;
        if (k ! = i) {
            long tcount = cell[k]. count;
            int  tchr = cell[k]. chr;
            cell[k]. count = cell[i]. count;
            cell[i]. count = tcount;
            cell[k]. chr = cell[i]. chr;
            cell[i]. chr = tchr;
        }
    }
    cell[0]. info = 1;

    /* ±×·ìÀ» ¼¼ºÐºñÀ² ÇØ, ºÎÈ£¾î¸¦ ¾ò´Â´Ù */
    for ( ; ; ) {
        /* ±×·ìÀÇ ¼±µÎ¸¦ ã¾Æ³½´Ù */
        for (i = 0, left = -1; i < size; i++)
            if (cell[i]. info == 1) {
                left = i;
                break;
            }
        if (left < 0) break;

        /* ±×·ìÀÇ ¸»¹Ì¸¦ ã¾Æ³½´Ù */
        for (i = left + 1, right = size - 1; i < size; i++)
            if (cell[i]. info > 0) {
                right = i - 1;
                break;
            }

        /* ±×·ì³»ÀÇ ÃâÇö ºóµµÀÇ È­ */
        for (i = left, sum = 0; i <= right; i++) sum += cell[i]. count;

        /* ±×·ìÀÇ ºÐÇÒ À§Ä¡ */
        for (mid = left, half = 0; mid < right && half < sum/2; mid++)
            half += cell[mid]. count;

        /* ºÎÈ£¾îÀÇ Ãß°¡ */
        for (i = left; i <= right; i++) {
            if (i<mid) cell[i]. code[cell[i]. len>>3]&=bit0[cell[i]. len&7];
            else       cell[i]. code[cell[i]. len>>3]|=bit1[cell[i]. len&7];
            cell[i]. len++;
        }
        if (mid == left + 1) cell[left]. info = 2;
        cell[mid]. info = (mid == right) ?  2 : 1;
    }
    *cellsize = size;
    return cell;
}