1 #target WASI
3 Function noMoreFreeMemory() Which Returns Nothing Is External;
4 Function segmentationFault() Which Returns Nothing Is External;
5 Function
6 printString(PointerToCharacter string) Which Returns Nothing Is External;
7 Function clearScreen() Which Returns Nothing Is External;
8 Function getLengthOfTheInput() Which Returns Integer16 Is External;
9 Function
10 getCharacterOfTheInput(Integer16 index) Which Returns Character Is External;
11 Function setDiagramWidth(Integer32 width) Which Returns Nothing Is External;
12 Function setDiagramHeight(Integer32 height) Which Returns Nothing Is External;
13 Function drawLine(Integer32 x1, Integer32 y1, Integer32 x2,
14 Integer32 y2) Which Returns Nothing Is External;
15 Function drawRectangle(Integer32 x, Integer32 y, Integer32 width,
16 Integer32 height) Which Returns Nothing Is External;
17 Function drawText(Integer32 x, Integer32 y,
18 PointerToCharacter text) Which Returns Nothing Is External;
19
20 Integer32 NDEBUG : = 1,
21 MAINTAIN_COMPATIBILITY_WITH_JAVASCRIPT_IMPLEMENTATION : = 1;
22
25 Structure TreeNode Consists Of {
26 Character character;
27 Integer16 frequencyOfCharacter;
28 PointerToTreeNode leftChild, rightChild;
29 Character code[16];
30 Integer32 x, y;
31 }
32 EndStructure;
33
34 InstantiateStructure TreeNode treeNodes[64];
35 Integer16 isTreeNodeUsed[64];
36
37 Function isTreeNodeWithinBounds(
38 PointerToTreeNode treeNode) Which Returns Integer32 Does {
39 Return AddressOf(treeNodes[0]) <= treeNode <= AddressOf(treeNodes[64 - 1]) and
40 mod(treeNode - AddressOf(treeNodes[0]), SizeOf(TreeNode)) =
41 0; }
44 EndFunction;
45
46 Function
47 convertIntegerToString(PointerToCharacter string,
48 Integer32 integer) Which Returns Nothing Is Declared;
49 Function strcat(PointerToCharacter dest,
50 PointerToCharacter src) Which Returns Nothing Is Declared;
51 Function strlen(PointerToCharacter string) Which Returns Integer32 Is Declared;
52
53 Function newTreeNode() Which Returns PointerToTreeNode Does {
54 Integer16 i : = 0;
55 While i < 64 Loop {
56 If not(isTreeNodeUsed[i]) Then {
57 treeNodes[i].character : = 0;
58 treeNodes[i].leftChild : = treeNodes[i].rightChild
59 : = PointerToTreeNode(0);
60 treeNodes[i].code[0] : = 0;
61 treeNodes[i].frequencyOfCharacter : = 0;
62 isTreeNodeUsed[i] : = 1;
63 If NDEBUG = 0 Then {
64 Character stringToBePrinted[64] : = {0};
65 strcat(AddressOf(stringToBePrinted[0]),
66 "NDEBUG: Allocating the TreeNode #");
67 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
68 strlen(AddressOf(stringToBePrinted[0])),
69 i);
70 strcat(AddressOf(stringToBePrinted[0]), "\n");
71 printString(AddressOf(stringToBePrinted[0]));
72 }
73 EndIf;
74 Return AddressOf(treeNodes[i]);
75 }
76 EndIf;
77 i += 1;
78 }
79 EndWhile;
80 noMoreFreeMemory();
81 }
82 EndFunction;
83
84 Function freeTreeNode(PointerToTreeNode treeNode) Which Returns Nothing Does {
85 If not(isTreeNodeWithinBounds(treeNode)) Then { segmentationFault(); }
86 EndIf;
87 If NDEBUG = 0 Then {
88 Character stringToBePrinted[64] : = {0};
89 strcat(AddressOf(stringToBePrinted[0]), "NDEBUG: Freeing the TreeNode #");
90 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
91 strlen(AddressOf(stringToBePrinted[0])),
92 (treeNode - AddressOf(treeNodes[0])) /
93 SizeOf(TreeNode));
94 strcat(AddressOf(stringToBePrinted[0]), "\n");
95 printString(AddressOf(stringToBePrinted[0]));
96 }
97 EndIf;
98 isTreeNodeUsed[(treeNode - AddressOf(treeNodes[0])) / SizeOf(TreeNode)] : = 0;
99 }
100 EndFunction;
101
102 Function getHeight(PointerToTreeNode node) Which Returns Integer32 Does {
103 If not(node) Then { Return 0; }
104 EndIf;
105 Integer32 max : = 0;
106 If getHeight(node->leftChild) > max Then {
107 max:
108 = getHeight(node->leftChild);
109 }
110 EndIf;
111 If getHeight(node->rightChild) > max Then {
112 max:
113 = getHeight(node->rightChild);
114 }
115 EndIf;
116 Return max + 1;
117 }
118 EndFunction;
119
120 Function strlen(PointerToCharacter str) Which Returns Integer32 Does {
121 If str = 0 Then { Return 0; }
122 EndIf;
123 Integer32 length : = 0;
124 While ValueAt(str + length) Loop { length += 1; }
125 EndWhile;
126 Return length;
127 }
128 EndFunction;
129
130 Function strncmp(PointerToCharacter first, PointerToCharacter second,
131 Integer32 n) Which Returns Integer32 Does {
132 If first = 0 or second = 0 Then { Return 1; }
133 EndIf;
134 Integer32 iterator : = 0;
135 While iterator < n Loop {
136 If ValueAt(first + iterator) = ValueAt(second + iterator) Then {
137 iterator += 1;
138 }
139 Else { Return ValueAt(first + iterator) - ValueAt(second + iterator); }
140 EndIf;
141 }
142 EndWhile;
143 Return 0;
144 }
145 EndFunction;
146
147 Function strcpy(PointerToCharacter dest,
148 PointerToCharacter src) Which Returns Nothing Does {
149 While ValueAt(src) Loop {
150 ValueAt(dest) : = ValueAt(src);
151 dest += 1;
152 src += 1;
153 }
154 EndWhile;
155 ValueAt(dest) : = 0;
156 }
157 EndFunction;
158
159 Function strcat(PointerToCharacter dest,
160 PointerToCharacter src) Which Returns Nothing Does {
161 strcpy(dest + strlen(dest), src);
162 }
163 EndFunction;
164
165 Function reverseString(PointerToCharacter string) Which Returns Nothing Does {
166 PointerToCharacter pointerToLastCharacter : = string + strlen(string) - 1;
167 While pointerToLastCharacter - string > 0 Loop {
168 Character tmp : = ValueAt(string);
169 ValueAt(string) : = ValueAt(pointerToLastCharacter);
170 ValueAt(pointerToLastCharacter) : = tmp;
171 string += 1;
172 pointerToLastCharacter -= 1;
173 }
174 EndWhile;
175 }
176 EndFunction;
177
178 Function convertIntegerToString(PointerToCharacter string,
179 Integer32 number) Which Returns Nothing Does {
180 Integer32 isNumberNegative : = 0;
181 If number < 0 Then {
182 number:
183 = -number;
184 isNumberNegative:
185 = 1;
186 }
187 EndIf;
188 Integer32 i : = 0;
189 While number >= 10 Loop {
190 ValueAt(string + i) : = '0' + mod(number, 10);
191 number /= 10;
192 i += 1;
193 }
194 EndWhile;
195 ValueAt(string + i) : = '0' + number;
196 i += 1;
197 If isNumberNegative Then {
198 ValueAt(string + i) : = '-';
199 i += 1;
200 }
201 EndIf;
202 ValueAt(string + i) : = 0;
203 reverseString(string);
204 }
205 EndFunction;
206
207 Function convertDecimalToString(PointerToCharacter string,
208 Decimal32 number) Which Returns Nothing Does {
209 convertIntegerToString(string, number);
210 number -= Integer32(number);
211 If number < 0 Then { number *= -1; }
212 EndIf;
213 If number = 0 Then { Return; }
214 EndIf;
215 strcat(string, ".");
216 Integer16 numberOfDecimals : = 0;
217 While numberOfDecimals<3 and number> 0 Loop {
218 numberOfDecimals += 1;
219 number *= 10;
220 Character stringWithTheNewDigit[2];
221 stringWithTheNewDigit[0] : = stringWithTheNewDigit[1] : = 0;
222 stringWithTheNewDigit[0] : = '0' + number;
223 strcat(string, AddressOf(stringWithTheNewDigit[0]));
224 number -= Integer32(number);
225 }
226 EndWhile;
227 }
228 EndFunction;
229
230 PointerToCharacter mapOfCodes[256];
231
232 Function assignCode(PointerToCharacter currentCode,
233 PointerToTreeNode treeNode) Which Returns Nothing Does {
234 If NDEBUG = 0 Then {
235 Character stringToBePrinted[64] : = {0};
236 strcat(AddressOf(stringToBePrinted[0]), "NDEBUG: Assigning the code \"");
237 strcat(AddressOf(stringToBePrinted[0]), currentCode);
238 strcat(AddressOf(stringToBePrinted[0]), "\" to the TreeNode #");
239 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
240 strlen(AddressOf(stringToBePrinted[0])),
241 (treeNode - AddressOf(treeNodes[0])) /
242 SizeOf(TreeNode));
243 strcat(AddressOf(stringToBePrinted[0]), ".\n");
244 printString(AddressOf(stringToBePrinted[0]));
245
246 stringToBePrinted[0] : = 0;
247 strcat(AddressOf(stringToBePrinted[0]),
248 "NDEBUG: Its left child is the TreeNode #");
249 If treeNode->leftChild Then {
250 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
251 strlen(AddressOf(stringToBePrinted[0])),
252 (treeNode->leftChild - AddressOf(treeNodes[0])) /
253 SizeOf(TreeNode));
254 }
255 Else { strcat(AddressOf(stringToBePrinted[0]), "null"); }
256 EndIf;
257 strcat(AddressOf(stringToBePrinted[0]), ".\n");
258 printString(AddressOf(stringToBePrinted[0]));
259
260 stringToBePrinted[0] : = 0;
261 strcat(AddressOf(stringToBePrinted[0]),
262 "NDEBUG: Its right child is the TreeNode #");
263 If treeNode->leftChild Then {
264 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
265 strlen(AddressOf(stringToBePrinted[0])),
266 (treeNode->rightChild - AddressOf(treeNodes[0])) /
267 SizeOf(TreeNode));
268 }
269 Else { strcat(AddressOf(stringToBePrinted[0]), "null"); }
270 EndIf;
271 strcat(AddressOf(stringToBePrinted[0]), ".\n");
272 printString(AddressOf(stringToBePrinted[0]));
273 }
274 EndIf;
275
276 If not(isTreeNodeWithinBounds(treeNode)) Then { segmentationFault(); }
277 EndIf;
278
279 strcpy(AddressOf(treeNode->code[0]), currentCode);
280
281 Character leftCode[16] : = {0}, rightCode[16] : = {0};
282
283 strcpy(AddressOf(leftCode[0]), currentCode);
284 strcat(AddressOf(leftCode[0]), "0");
285 strcpy(AddressOf(rightCode[0]), currentCode);
286 strcat(AddressOf(rightCode[0]), "1");
287
288 If treeNode->leftChild Then {
289 assignCode(AddressOf(leftCode[0]), treeNode->leftChild);
290 }
291 EndIf;
292 If treeNode->rightChild Then {
293 assignCode(AddressOf(rightCode[0]), treeNode->rightChild);
294 }
295 EndIf;
296
297 If treeNode->character Then {
298 mapOfCodes[treeNode->character] : = AddressOf(treeNode->code[0]);
299 Character codeToPrint[32] : = {0};
300 codeToPrint[0] : = '\'';
301 codeToPrint[1] : = treeNode->character;
302 codeToPrint[2] : = '\'';
303 codeToPrint[3] : = '=';
304 codeToPrint[4] : = '>';
305 codeToPrint[5] : = 0;
306 strcat(AddressOf(codeToPrint[0]), AddressOf(treeNode->code[0]));
307 strcat(AddressOf(codeToPrint[0]), "\n");
308 printString(AddressOf(codeToPrint[0]));
309 }
310 EndIf;
311 }
312 EndFunction;
313
314 Function freeUpTheTree(PointerToTreeNode tree) Which Returns Nothing Does {
315 If tree->leftChild Then {
316 freeUpTheTree(tree->leftChild); }
319 EndIf;
320 If tree->rightChild Then { freeUpTheTree(tree->rightChild); }
321 EndIf;
322 freeTreeNode(tree);
323 }
324 EndFunction;
325
326 Decimal32 PRECISION : = 500;
327 Function ln(Decimal32 x) Which Returns Decimal32 Does {
328 Decimal32 sum : = 0, epsilon : = (x - 1) / (5 * PRECISION), i : = 1;
330 While(epsilon > 0 and i < x) or (epsilon < 0 and i > x) Loop {
331 sum += epsilon / i;
332 i += epsilon;
333 }
334 EndWhile;
335 Return sum;
336 }
337 EndFunction;
338
339 Function log2(Decimal32 x) Which Returns Decimal32 Does {
340 Return ln(x) / ln(2);
341 }
342 EndFunction;
343
344 Character input[64];
345 Character output[256];
346
347 Function getAddressOfTheOutput() Which Returns PointerToCharacter
348 Does { Return AddressOf(output[0]);
354 }
355 EndFunction;
356
357 Function shl(Integer32 x, Integer32 y) Which Returns Integer32 Does {
358 Return asm_i32(R"WebAssembly(
359 (i32.shl
360 (i32.load %x)
361 (i32.load %y)
362 )
363 )WebAssembly");
364 }
365 EndFunction;
366
367 Structure Maxima Consists Of { Integer32 minimumX, maximumX; }
368 EndStructure;
369 Integer32 minimumX, maximumX;
370
371 Function
372 findMinimumAndMaximumX(PointerToTreeNode node,
373 PointerToMaxima maxima) Which Returns Nothing Does {
374 If node->x < maxima->minimumX Then { maxima->minimumX : = node->x; }
375 EndIf;
376 If node->x > maxima->maximumX Then { maxima->maximumX : = node->x; }
377 EndIf;
378
379 If node->rightChild Then { findMinimumAndMaximumX(node->rightChild, maxima); }
380 EndIf;
381 If node->leftChild Then { findMinimumAndMaximumX(node->leftChild, maxima); }
382 EndIf;
383 }
384 EndFunction;
385
386 Function setCoordinates(PointerToTreeNode node, Integer32 x, Integer32 y,
387 Integer32 space) Which Returns Nothing Does {
388 node->x : = x;
389 node->y : = y;
390 If node->leftChild Then {
391 Integer32 newX : = x - space - 10;
392 While 1 Loop {
393 newX += 10;
394 setCoordinates(node->leftChild, newX, y + 75,
395 20 * shl(1, getHeight(node->leftChild) - 1));
396 InstantiateStructure Maxima localMaxima;
397 localMaxima.maximumX : = localMaxima.minimumX : = newX;
398 findMinimumAndMaximumX(node->leftChild, AddressOf(localMaxima));
399 If x - localMaxima.maximumX <= 60 Then { Break; }
400 EndIf;
401 }
402 EndWhile;
403 }
404 EndIf;
405 If node->rightChild Then {
406 Integer32 newX : = x + space + 10;
407 While 1 Loop {
408 newX -= 10;
409 setCoordinates(node->rightChild, newX, y + 75,
410 20 * shl(1, getHeight(node->rightChild) - 1));
411 InstantiateStructure Maxima localMaxima;
412 localMaxima.maximumX : = localMaxima.minimumX : = newX;
413 findMinimumAndMaximumX(node->rightChild, AddressOf(localMaxima));
414 If localMaxima.minimumX - x <= 40 Then { Break; }
415 EndIf;
416 }
417 EndWhile;
418 }
419 EndIf;
420 }
421 EndFunction;
422
423 Function drawTree(PointerToTreeNode node) Which Returns Nothing Does {
424 drawRectangle(node->x - minimumX, node->y, 50, 50);
425 If node->character Then {
426 Character output[4];
427 output[0] : = '\'';
428 output[1] : = node->character;
429 output[2] : = '\'';
430 output[3] : = 0;
431 drawText(node->x + 5 - minimumX, node->y + 20, AddressOf(output[0]));
432 }
433 EndIf;
434 Character output[8];
435 output[0] : = 0;
436 convertIntegerToString(AddressOf(output[0]), node->frequencyOfCharacter);
437 strcat(AddressOf(output[0]), "/");
438 convertIntegerToString(AddressOf(output[0]) + strlen(AddressOf(output[0])),
439 getLengthOfTheInput());
440 drawText(node->x + 5 - minimumX, node->y + 40, AddressOf(output[0]));
441 If node->leftChild Then {
442 drawText(node->x - minimumX - 10, node->y + 60, "0");
443 drawLine(node->x + 25 - minimumX, node->y + 50, node->x + 25 - minimumX,
444 node->y + 50 + 13);
445 drawLine(node->x + 25 - minimumX, node->y + 50 + 13,
446 node->leftChild->x + 25 - minimumX, node->y + 50 + 13);
447 drawLine(node->leftChild->x + 25 - minimumX, node->y + 50 + 13,
448 node->leftChild->x + 25 - minimumX, node->leftChild->y);
449 drawTree(node->leftChild);
450 }
451 EndIf;
452 If node->rightChild Then {
453 drawText(node->x - minimumX + 50, node->y + 60, "1");
454 drawLine(node->x + 25 - minimumX, node->y + 50, node->x + 25 - minimumX,
455 node->y + 50 + 13);
456 drawLine(node->x + 25 - minimumX, node->y + 50 + 13,
457 node->rightChild->x + 25 - minimumX, node->y + 50 + 13);
458 drawLine(node->rightChild->x + 25 - minimumX, node->y + 50 + 13,
459 node->rightChild->x + 25 - minimumX, node->rightChild->y);
460 drawTree(node->rightChild);
461 }
462 EndIf;
463 }
464 EndFunction;
465
466 Function main() Which Returns Nothing Does {
467 clearScreen();
468 Integer16 lengthOfInput : = getLengthOfTheInput(), i : = 0;
469 If NDEBUG = 0 Then {
470 Character stringToBePrinted[64] : = {0};
471 strcat(AddressOf(stringToBePrinted[0]),
472 "NDEBUG: The length of the input is: ");
473 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
474 strlen(AddressOf(stringToBePrinted[0])),
475 lengthOfInput);
476 strcat(AddressOf(stringToBePrinted[0]), "\n");
477 printString(AddressOf(stringToBePrinted[0]));
478 }
479 EndIf;
480 While i < lengthOfInput Loop {
481 input[i] : = getCharacterOfTheInput(i);
482 i += 1;
483 }
484 EndWhile;
485 input[lengthOfInput] : = 0;
486
487 If strlen(AddressOf(input[0])) = 0 Then {
488 printString("The input is empty!\n");
489 Return;
490 }
491 EndIf;
492
493 i:
494 = 0;
495 While i < 256 Loop {
496 mapOfCodes[i] : = PointerToCharacter(0);
497 i += 1;
498 }
499 EndWhile;
500
501 PointerToTreeNode array[32];
502 Integer16 lengthOfTheArray : = 0;
503 i:
504 = 0;
505 While i < lengthOfInput Loop {
506 Integer16 j : = 0, haveWeFoundTheCharacterInTheArray : = 0;
507 While j < lengthOfTheArray Loop {
508 If array[j]->character = input[i] Then {
509 haveWeFoundTheCharacterInTheArray:
510 = 1;
511 array[j]->frequencyOfCharacter += 1;
512 }
513 EndIf;
514 j += 1;
515 }
516 EndWhile;
517 If not(haveWeFoundTheCharacterInTheArray) Then {
518 array[lengthOfTheArray] : = newTreeNode();
519 array[lengthOfTheArray]->character : = input[i];
520 array[lengthOfTheArray]->frequencyOfCharacter : = 1;
521 lengthOfTheArray += 1;
522 }
523 EndIf;
524 i += 1;
525 }
526 EndWhile;
527
528 i:
529 = 0;
530 While i < lengthOfTheArray Loop {
531 Character stringToBePrinted[64] : = {0};
532 strcat(AddressOf(stringToBePrinted[0]), "The character '");
533 Integer16 indexOfCharacter : = strlen(AddressOf(stringToBePrinted[0]));
534 stringToBePrinted[indexOfCharacter] : = array[i]->character;
535 stringToBePrinted[indexOfCharacter + 1] : = 0;
536 strcat(AddressOf(stringToBePrinted[0]), "' has the frequency of ");
537 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
538 strlen(AddressOf(stringToBePrinted[0])),
539 array[i]->frequencyOfCharacter);
540 strcat(AddressOf(stringToBePrinted[0]), ".\n");
541 printString(AddressOf(stringToBePrinted[0]));
542 i += 1;
543 }
544 EndWhile;
545
546 Decimal32 ShannonEntropy : = 0;
547 i:
548 = 0;
549 While i < lengthOfTheArray Loop {
550 ShannonEntropy -=
551 (array[i]->frequencyOfCharacter / Decimal32(lengthOfInput)) *
552 log2(array[i]->frequencyOfCharacter / Decimal32(lengthOfInput));
553 i += 1;
554 }
555 EndWhile;
556 output[0] : = 0;
557 strcat(AddressOf(output[0]), "The Shannon Entropy of the input string is: ");
558 convertDecimalToString(AddressOf(output[0]) + strlen(AddressOf(output[0])),
559 ShannonEntropy);
560 strcat(AddressOf(output[0]), " bits/symbol.\n");
561 printString(AddressOf(output[0]));
562
563 While lengthOfTheArray > 1 Loop {
564 Integer16 minimum : = 0, secondMinimum : = 0;
565
566 Integer16 i : = 0;
567 If NDEBUG = 0 Then {
568 Character stringToBePrinted[64] : = {0};
569 strcat(AddressOf(stringToBePrinted[0]),
570 "NDEBUG: The length of the array is ");
571 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
572 strlen(AddressOf(stringToBePrinted[0])),
573 lengthOfTheArray);
574 strcat(AddressOf(stringToBePrinted[0]), ".\n");
575 printString(AddressOf(stringToBePrinted[0]));
576 }
577 EndIf;
578 While i < lengthOfTheArray Loop {
579 If NDEBUG = 0 Then {
580 Character stringToBePrinted[64] : = {0};
581 strcat(AddressOf(stringToBePrinted[0]),
582 "NDEBUG: The tree at the index #");
583 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
584 strlen(AddressOf(stringToBePrinted[0])),
585 i);
586 strcat(AddressOf(stringToBePrinted[0]), " is the TreeNode #");
587 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
588 strlen(AddressOf(stringToBePrinted[0])),
589 (array[i] - AddressOf(treeNodes[0])) /
590 SizeOf(TreeNode));
591 strcat(AddressOf(stringToBePrinted[0]), ".\n");
592 printString(AddressOf(stringToBePrinted[0]));
593 }
594 EndIf;
595 If not(isTreeNodeWithinBounds(array[i])) Then {
596 segmentationFault();
597 Return;
598 }
599 EndIf;
600 i += 1;
601 }
602 EndWhile;
603
604 i:
605 = 0;
606 While i < lengthOfTheArray Loop {
607 If array[i]->frequencyOfCharacter <
608 array[minimum]->frequencyOfCharacter Then {
609 minimum:
610 = i;
611 }
612 EndIf;
613 i += 1;
614 }
615 EndWhile;
616
617 i:
618 = minimum = 0 ? 1 : 0;
619 secondMinimum:
620 = i;
621 While i < lengthOfTheArray Loop {
622 If array[i]->frequencyOfCharacter <
623 array[secondMinimum]->frequencyOfCharacter and
624 not(i = minimum) Then {
625 secondMinimum:
626 = i;
627 }
628 EndIf;
629 i += 1;
630 }
631 EndWhile;
632
633 If NDEBUG = 0 Then {
634 Character stringToBePrinted[64] : = {0};
635 strcat(AddressOf(stringToBePrinted[0]),
636 "NDEBUG: The minimum and the second minimum are ");
637 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
638 strlen(AddressOf(stringToBePrinted[0])),
639 minimum);
640 strcat(AddressOf(stringToBePrinted[0]), " and ");
641 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
642 strlen(AddressOf(stringToBePrinted[0])),
643 secondMinimum);
644 strcat(AddressOf(stringToBePrinted[0]), ".\n");
645 printString(AddressOf(stringToBePrinted[0]));
646 }
647 EndIf;
648
649 If NDEBUG = 0 Then {
650 Character stringToBePrinted[64] : = {0};
651 strcat(AddressOf(stringToBePrinted[0]), "NDEBUG: Joining the TreeNode #");
652 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
653 strlen(AddressOf(stringToBePrinted[0])),
654 (array[minimum] - AddressOf(treeNodes[0])) /
655 SizeOf(TreeNode));
656 strcat(AddressOf(stringToBePrinted[0]), " with the TreeNode #");
657 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
658 strlen(AddressOf(stringToBePrinted[0])),
659 (array[secondMinimum] - AddressOf(treeNodes[0])) /
660 SizeOf(TreeNode));
661 strcat(AddressOf(stringToBePrinted[0]), ".\n");
662 printString(AddressOf(stringToBePrinted[0]));
663 }
664 EndIf;
665
666 PointerToTreeNode sumOfTheTwoMostFrequent : = newTreeNode();
667 sumOfTheTwoMostFrequent->frequencyOfCharacter
668 : = array[minimum]->frequencyOfCharacter +
669 array[secondMinimum]->frequencyOfCharacter;
670 sumOfTheTwoMostFrequent->leftChild : = array[minimum];
671 sumOfTheTwoMostFrequent->rightChild : = array[secondMinimum];
672
673 If NDEBUG = 0 Then {
674 Character stringToBePrinted[64] : = {0};
675 strcat(AddressOf(stringToBePrinted[0]),
676 "NDEBUG: The new TreeNode has the frequency of: ");
677 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
678 strlen(AddressOf(stringToBePrinted[0])),
679 sumOfTheTwoMostFrequent->frequencyOfCharacter);
680 strcat(AddressOf(stringToBePrinted[0]), ".\n");
681 printString(AddressOf(stringToBePrinted[0]));
682 }
683 EndIf;
684
685 If not(MAINTAIN_COMPATIBILITY_WITH_JAVASCRIPT_IMPLEMENTATION) Then {
686 array[minimum] : = sumOfTheTwoMostFrequent;
687 }
688 EndIf;
689
690 i:
692 = secondMinimum;
693 While i < lengthOfTheArray - 1 Loop {
694 array[i] : = array[i + 1];
695 i += 1;
696 }
697 EndWhile;
698 lengthOfTheArray -= 1;
699 If not(MAINTAIN_COMPATIBILITY_WITH_JAVASCRIPT_IMPLEMENTATION) Then {
700 Continue;
701 }
702 EndIf;
703 If minimum >
705 secondMinimum Then { minimum -= 1;
708 }
709 EndIf;
710 i:
711 = minimum;
712 While i < lengthOfTheArray - 1 Loop {
713 array[i] : = array[i + 1];
714 i += 1;
715 }
716 EndWhile;
717 array[lengthOfTheArray - 1] : = sumOfTheTwoMostFrequent;
718 }
719 EndWhile;
720
721 If NDEBUG = 0 Then {
722 Character stringToBePrinted[128] : = {0};
723 strcat(AddressOf(stringToBePrinted[0]),
724 "NDEBUG: The frequency of the root node is ");
725 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
726 strlen(AddressOf(stringToBePrinted[0])),
727 array[0]->frequencyOfCharacter);
728 strcat(AddressOf(stringToBePrinted[0]),
729 ". If the algorithm is correctly implemented, it should be ");
730 convertIntegerToString(AddressOf(stringToBePrinted[0]) +
731 strlen(AddressOf(stringToBePrinted[0])),
732 lengthOfInput);
733 strcat(AddressOf(stringToBePrinted[0]), ".\n");
734 printString(AddressOf(stringToBePrinted[0]));
735 }
736 EndIf;
737
738 printString("The tree has been constructed, let us assign Huffman codes to "
739 "characters:\n");
740 assignCode("", array[0]);
741
742 Integer16 lengthOfTheOutput : = 0;
743 i:
744 = 0;
745 While i < lengthOfInput Loop {
746 lengthOfTheOutput += strlen(mapOfCodes[input[i]]);
747 i += 1;
748 }
749 EndWhile;
750 output[0] : = 0;
751 strcat(AddressOf(output[0]), "The length of the encoded string is: ");
752 convertIntegerToString(AddressOf(output[0]) + strlen(AddressOf(output[0])),
753 lengthOfTheOutput);
754 strcat(AddressOf(output[0]), " bits.\n");
755 printString(AddressOf(output[0]));
756
757 output[0] : = 0;
758 strcat(AddressOf(output[0]),
759 "The average length of the symbol in the Huffman code is: ");
760 convertDecimalToString(AddressOf(output[0]) + strlen(AddressOf(output[0])),
761 Decimal32(lengthOfTheOutput) / lengthOfInput);
762 strcat(AddressOf(output[0]), " bits/symbol.\n");
763 printString(AddressOf(output[0]));
764
765 output[0] : = 0;
766 i:
767 = 0;
768 While i < lengthOfInput Loop {
769 strcat(AddressOf(output[0]), mapOfCodes[input[i]]);
770 i += 1;
771 }
772 EndWhile;
773 strcat(AddressOf(output[0]), "\n");
774 printString("The Huffman code of the input is:\n");
775 printString(AddressOf(output[0]));
776
777 setCoordinates(array[0], 0, 0, 10 * shl(1, getHeight(array[0])));
778 InstantiateStructure Maxima globalMaxima;
779 globalMaxima.minimumX : = globalMaxima.maximumX : = 0;
780 findMinimumAndMaximumX(array[0], AddressOf(globalMaxima));
781 minimumX:
782 = globalMaxima.minimumX;
783 maximumX:
784 = globalMaxima.maximumX;
785 drawTree(array[0]);
786 setDiagramWidth(maximumX - minimumX + 55);
787 setDiagramHeight(getHeight(array[0]) * 75);
788
789 freeUpTheTree(array[0]);
790
791 Character stringToBePrinted[64] : = {0};
792 strcat(AddressOf(stringToBePrinted[0]), "Decoding the output...\n");
793 printString(AddressOf(stringToBePrinted[0]));
794
795 Integer16 j : = 0, k : = 0;
796 While j < strlen(AddressOf(output[0])) - 1 Loop {
797 i:
798 = 0;
799 If NDEBUG = 0 Then {
800 printString(
801 "NDEBUG: We are entering the loop for decoding the output!\n");
802 }
803 EndIf;
804 While(mapOfCodes[i] = 0 or strncmp(AddressOf(output[j]), mapOfCodes[i],
805 strlen(mapOfCodes[i]))) and
806 i < 256 Loop {
807 If NDEBUG = 0 Then {
808 If mapOfCodes[i] = 0 Then {
809 printString("NDEBUG: Skipping the character because it's NULL.\n");
810 }
811 Else {
812 printString(
813 "NDEBUG: Skipping the character because it doesn't match!\n");
814 }
815 EndIf;
816 }
817 EndIf;
818 i += 1;
819 }
820 EndWhile;
821 If i = 256 Then {
822 printString("ERROR: Cannot find the beginning of the current string in "
823 "the map of codes!\n");
824 Return;
825 }
826 EndIf;
827 stringToBePrinted[0] : = 0;
828 strcat(AddressOf(stringToBePrinted[0]), mapOfCodes[i]);
829 strcat(AddressOf(stringToBePrinted[0]), "=>");
830 Character stringToBeAdded[5] : = {'\'', i, '\'', '\n', 0};
831 strcat(AddressOf(stringToBePrinted[0]), AddressOf(stringToBeAdded[0]));
832 printString(AddressOf(stringToBePrinted[0]));
833 j += strlen(mapOfCodes[i]);
834 If not(i = getCharacterOfTheInput(k)) Then {
835 printString("ERROR: The decoded output does not match the input!\n");
836 Break;
837 }
838 EndIf;
839 k += 1;
840 }
841 EndWhile;
842 }
843 EndFunction;
844