#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char buf[] = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzvvvvvvvvvvvvvvxxxxxxxxxxxxxxxxxxxddddddddd";
int counts[256];
//int testdata[] = { 2, 3, 3, 4, 13, 14 };
int testdata[] = { 1, 1, 1, 2, 3, 5, 6, 6, 6, 6, 6 };
int tdsize = sizeof(testdata)/sizeof(*testdata);
static int cmpint(const void *p1, const void *p2);
void disp_array(char const * const title, int A[], int n);
void inplace_huffman_p1(int *A, int n) {
int i;
// Phase 1
int s,r,t;
for(s=0, r=0, t=0; t<n-1; t++) {
int sum = 0;
for(i=0; i<2; i++) {
if(s>=n || (r<t && A[r]<A[s])) {
sum += A[r];
A[r] = t;
r++;
}
else {
sum += A[s];
if(s > t) {
A[s] = 0;
}
s++;
}
}
A[t] = sum;
}
disp_array("Phase 1", A, n);
}
void inplace_huffman_p2(int *A, int n) {
// Phase 2
int level_top = n - 2; //root
int depth = 1;
int i = n, j, k;
int total_nodes_at_level = 2;
while(i > 0) {
for(k=level_top; k>0 && A[k-1]>=level_top; k--) {}
int internal_nodes_at_level = level_top - k;
int leaves_at_level = total_nodes_at_level - internal_nodes_at_level;
for(j=0; j<leaves_at_level; j++) {
A[--i] = depth;
}
total_nodes_at_level = internal_nodes_at_level * 2;
level_top = k;
depth++;
}
disp_array("Phase 2", A, n);
}
void n_to_binary_str(int n);
int check_code_kraft(int *A, int n) {
int i, sum=0;
int largep2 = 1 << 30;
for(i=0; i<n; i++) {
sum += largep2 >> A[i];
//printf("Check: sum = %x. (sum==largep2)==%d\n", sum, sum == largep2);
//n_to_binary_str(sum);
//putchar('\n');
}
//printf("Check: sum = %x. (sum==largep2)==%d\n", sum, sum == largep2);
return sum==largep2;
}
int calc_code_cost(int *A, int n) {
int i, sum=0;
for(i=0; i<n; i++) {
sum += A[i] * testdata[i];
}
return sum;
}
void n_to_binary_str(int n) {
char str[30], *p=str, *octal_to_binary[] = {
"000", "001", "010", "011",
"100", "101", "111"
};
while(*p) {
printf("%s", octal_to_binary
[*p
- '0']); p++;
}
}
int main() {
int A[256],i,n;
int alphasize = sizeof(A)/sizeof(*A);
#if 0
for(i
=0; i
<strlen(buf
); i
++) { counts[buf[i]]++;
}
n=0;
for(i=0; i<alphasize; i++) {
if(counts[i] != 0) {
A[n++] = counts[i];
}
}
qsort(A
, n
, sizeof(A
[0]), cmpint
); #endif
#if 1
memcpy(A
, testdata
, tdsize
* sizeof(testdata
[0])); n = tdsize;
qsort(A
, n
, sizeof(A
[0]), cmpint
); #endif
disp_array("Phase 0", A, n);
inplace_huffman_p1(A, n);
inplace_huffman_p2(A, n);
if(!check_code_kraft(A, n)) {
printf("Failed Kraft ineq!\n"); }
else {
printf("Passed Kraft check.\n"); }
int cost=calc_code_cost(A, n);
printf("Total code cost: %d\n", cost
);
return 0;
}
void disp_array(char const * const title, int A[], int n)
{
int i;
for(i=0; i<n; i++) {
if(i>0) {
}
}
}
static int cmpint(const void *p1, const void *p2) {
return *((const int *)p1) - *((const int *)p2);
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgoKCmNoYXIgYnVmW10gPSAienp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6dnZ2dnZ2dnZ2dnZ2dnZ4eHh4eHh4eHh4eHh4eHh4eHh4ZGRkZGRkZGRkIjsKaW50IGNvdW50c1syNTZdOwovL2ludCB0ZXN0ZGF0YVtdID0geyAyLCAzLCAzLCA0LCAxMywgMTQgfTsKaW50IHRlc3RkYXRhW10gPSB7IDEsIDEsIDEsIDIsIDMsIDUsIDYsIDYsIDYsIDYsIDYgfTsKaW50IHRkc2l6ZSA9IHNpemVvZih0ZXN0ZGF0YSkvc2l6ZW9mKCp0ZXN0ZGF0YSk7CgpzdGF0aWMgaW50IGNtcGludChjb25zdCB2b2lkICpwMSwgY29uc3Qgdm9pZCAqcDIpOwoKdm9pZCBkaXNwX2FycmF5KGNoYXIgY29uc3QgKiBjb25zdCB0aXRsZSwgaW50IEFbXSwgaW50IG4pOwoKdm9pZCBpbnBsYWNlX2h1ZmZtYW5fcDEoaW50ICpBLCBpbnQgbikgewoJaW50IGk7CgkKCS8vIFBoYXNlIDEKCWludCBzLHIsdDsKCWZvcihzPTAsIHI9MCwgdD0wOyB0PG4tMTsgdCsrKSB7CgkJaW50IHN1bSA9IDA7CgkJZm9yKGk9MDsgaTwyOyBpKyspIHsKCQkJaWYocz49biB8fCAocjx0ICYmIEFbcl08QVtzXSkpIHsKCQkJCXN1bSArPSBBW3JdOwoJCQkJQVtyXSA9IHQ7CgkJCQlyKys7CgkJCX0KCQkJZWxzZSB7CgkJCQlzdW0gKz0gQVtzXTsKCQkJCWlmKHMgPiB0KSB7CgkJCQkJQVtzXSA9IDA7CgkJCQl9CgkJCQlzKys7CgkJCX0KCQl9CgkJQVt0XSA9IHN1bTsKCX0KCQoJZGlzcF9hcnJheSgiUGhhc2UgMSIsIEEsIG4pOwp9Cgp2b2lkIGlucGxhY2VfaHVmZm1hbl9wMihpbnQgKkEsIGludCBuKSB7CgkvLyBQaGFzZSAyCglpbnQgbGV2ZWxfdG9wID0gbiAtIDI7IC8vcm9vdAoJaW50IGRlcHRoID0gMTsKCWludCBpID0gbiwgaiwgazsKCWludCB0b3RhbF9ub2Rlc19hdF9sZXZlbCA9IDI7Cgl3aGlsZShpID4gMCkgewoJCWZvcihrPWxldmVsX3RvcDsgaz4wICYmIEFbay0xXT49bGV2ZWxfdG9wOyBrLS0pIHt9CgoJCWludCBpbnRlcm5hbF9ub2Rlc19hdF9sZXZlbCA9IGxldmVsX3RvcCAtIGs7CgkJaW50IGxlYXZlc19hdF9sZXZlbCA9IHRvdGFsX25vZGVzX2F0X2xldmVsIC0gaW50ZXJuYWxfbm9kZXNfYXRfbGV2ZWw7CgkJZm9yKGo9MDsgajxsZWF2ZXNfYXRfbGV2ZWw7IGorKykgewoJCQlBWy0taV0gPSBkZXB0aDsKCQl9CgoJCXRvdGFsX25vZGVzX2F0X2xldmVsID0gaW50ZXJuYWxfbm9kZXNfYXRfbGV2ZWwgKiAyOwoJCWxldmVsX3RvcCA9IGs7CgkJZGVwdGgrKzsKCX0KCglkaXNwX2FycmF5KCJQaGFzZSAyIiwgQSwgbik7CgkKfQoKdm9pZCBuX3RvX2JpbmFyeV9zdHIoaW50IG4pOwoKaW50IGNoZWNrX2NvZGVfa3JhZnQoaW50ICpBLCBpbnQgbikgewoJaW50IGksIHN1bT0wOwoJaW50IGxhcmdlcDIgPSAxIDw8IDMwOwoJZm9yKGk9MDsgaTxuOyBpKyspIHsKCQlzdW0gKz0gbGFyZ2VwMiA+PiBBW2ldOwoJCQkvL3ByaW50ZigiQ2hlY2s6IHN1bSA9ICV4LiAoc3VtPT1sYXJnZXAyKT09JWRcbiIsIHN1bSwgc3VtID09IGxhcmdlcDIpOwoJCQkvL25fdG9fYmluYXJ5X3N0cihzdW0pOwoJCQkvL3B1dGNoYXIoJ1xuJyk7Cgl9CgkvL3ByaW50ZigiQ2hlY2s6IHN1bSA9ICV4LiAoc3VtPT1sYXJnZXAyKT09JWRcbiIsIHN1bSwgc3VtID09IGxhcmdlcDIpOwoJcmV0dXJuIHN1bT09bGFyZ2VwMjsKfQoKaW50IGNhbGNfY29kZV9jb3N0KGludCAqQSwgaW50IG4pIHsKCWludCBpLCBzdW09MDsKCWZvcihpPTA7IGk8bjsgaSsrKSB7CgkJc3VtICs9IEFbaV0gKiB0ZXN0ZGF0YVtpXTsKCX0KCXJldHVybiBzdW07Cn0KCnZvaWQgbl90b19iaW5hcnlfc3RyKGludCBuKSB7CgljaGFyIHN0clszMF0sICpwPXN0ciwgKm9jdGFsX3RvX2JpbmFyeVtdID0gewoJCSIwMDAiLCAiMDAxIiwgIjAxMCIsICIwMTEiLAoJCSIxMDAiLCAiMTAxIiwgIjExMSIKCQl9OwoJc3ByaW50ZihzdHIsICIlMDExbyIsIG4pOwoJd2hpbGUoKnApIHsKCQlwcmludGYoIiVzIiwgb2N0YWxfdG9fYmluYXJ5WypwIC0gJzAnXSk7CgkJcCsrOwoJfQp9CgppbnQgbWFpbigpIHsKCWludCBBWzI1Nl0saSxuOwoJaW50IGFscGhhc2l6ZSA9IHNpemVvZihBKS9zaXplb2YoKkEpOwoKI2lmIDAKCWZvcihpPTA7IGk8c3RybGVuKGJ1Zik7IGkrKykgewoJCWNvdW50c1tidWZbaV1dKys7Cgl9CgoJbj0wOwoJZm9yKGk9MDsgaTxhbHBoYXNpemU7IGkrKykgewoJCWlmKGNvdW50c1tpXSAhPSAwKSB7CgkJCUFbbisrXSA9IGNvdW50c1tpXTsKCQl9Cgl9CgoJcXNvcnQoQSwgbiwgc2l6ZW9mKEFbMF0pLCBjbXBpbnQpOwojZW5kaWYKCgkKI2lmIDEKCW1lbWNweShBLCB0ZXN0ZGF0YSwgdGRzaXplICogc2l6ZW9mKHRlc3RkYXRhWzBdKSk7CgluID0gdGRzaXplOwoJcXNvcnQoQSwgbiwgc2l6ZW9mKEFbMF0pLCBjbXBpbnQpOwojZW5kaWYKCQoJZGlzcF9hcnJheSgiUGhhc2UgMCIsIEEsIG4pOwoKCWlucGxhY2VfaHVmZm1hbl9wMShBLCBuKTsKCWlucGxhY2VfaHVmZm1hbl9wMihBLCBuKTsKCglpZighY2hlY2tfY29kZV9rcmFmdChBLCBuKSkgewoJCXByaW50ZigiRmFpbGVkIEtyYWZ0IGluZXEhXG4iKTsKCX0KCWVsc2UgewoJCXByaW50ZigiUGFzc2VkIEtyYWZ0IGNoZWNrLlxuIik7Cgl9CgoJaW50IGNvc3Q9Y2FsY19jb2RlX2Nvc3QoQSwgbik7CglwcmludGYoIlRvdGFsIGNvZGUgY29zdDogJWRcbiIsIGNvc3QpOwoJCglyZXR1cm4gMDsKfQoKdm9pZCBkaXNwX2FycmF5KGNoYXIgY29uc3QgKiBjb25zdCB0aXRsZSwgaW50IEFbXSwgaW50IG4pCnsKCWludCBpOwoJcHJpbnRmKCIlczpcbiIsIHRpdGxlKTsKCWZvcihpPTA7IGk8bjsgaSsrKSB7CgkJaWYoaT4wKSB7CgkJCXB1dGNoYXIoJ3wnKTsKCQl9CgkJcHJpbnRmKCIlZCIsIEFbaV0pOwoJfQoJcHV0Y2hhcignXG4nKTsKfQoKc3RhdGljIGludCBjbXBpbnQoY29uc3Qgdm9pZCAqcDEsIGNvbnN0IHZvaWQgKnAyKSB7CglyZXR1cm4gKigoY29uc3QgaW50ICopcDEpIC0gKigoY29uc3QgaW50ICopcDIpOwp9Cg==