1 Function noMoreFreeMemory() Which Returns Nothing Is External;
   2 Function segmentationFault() Which Returns Nothing Is External;
   3 Function
   4 printString(PointerToCharacter string) Which Returns Nothing Is External;
   5 Function clearScreen() Which Returns Nothing Is External;
   6 Function getLengthOfTheInput() Which Returns Integer16 Is External;
   7 Function
   8 getCharacterOfTheInput(Integer16 index) Which Returns Character Is External;
   9 
  10 Integer32 NDEBUG : = 1,
  11                  MAINTAIN_COMPATIBILITY_WITH_JAVASCRIPT_IMPLEMENTATION : = 1;
  12 // The JavaScript implementation is available here:
  13 // https://flatassembler.github.io/huffman.html
  14 
  15 Structure TreeNode Consists Of {
  16   Character character;
  17   Integer16 frequencyOfCharacter;
  18   PointerToTreeNode leftChild, rightChild;
  19   Character code[16];
  20 }
  21 EndStructure;
  22 
  23 InstantiateStructure TreeNode treeNodes[64];
  24 Integer16 isTreeNodeUsed[64];
  25 
  26 Function isTreeNodeWithinBounds(
  27     PointerToTreeNode treeNode) Which Returns Integer32 Does {
  28   Return AddressOf(treeNodes[0]) <= treeNode <= AddressOf(treeNodes[64 - 1]) and
  29       mod(treeNode - AddressOf(treeNodes[0]), SizeOf(TreeNode)) =
  30       0; // In C, testing whether the mod is equal to 0 would not be necessary,
  31          // but, since AEC supports unaligned access, it is necessary here.
  32 }
  33 EndFunction;
  34 
  35 Function
  36 convertIntegerToString(PointerToCharacter string,
  37                        Integer32 integer) Which Returns Nothing Is Declared;
  38 Function strcat(PointerToCharacter dest,
  39                 PointerToCharacter src) Which Returns Nothing Is Declared;
  40 Function strlen(PointerToCharacter string) Which Returns Integer32 Is Declared;
  41 
  42 Function newTreeNode() Which Returns PointerToTreeNode Does {
  43   Integer16 i : = 0;
  44   While i < 64 Loop {
  45     If not(isTreeNodeUsed[i]) Then {
  46       treeNodes[i].character : = 0;
  47       treeNodes[i].leftChild : = treeNodes[i].rightChild
  48           : = PointerToTreeNode(0);
  49       treeNodes[i].code[0] : = 0;
  50       treeNodes[i].frequencyOfCharacter : = 0;
  51       isTreeNodeUsed[i] : = 1;
  52       If NDEBUG = 0 Then {
  53         Character stringToBePrinted[64] : = {0};
  54         strcat(AddressOf(stringToBePrinted[0]),
  55                "NDEBUG: Allocating the TreeNode #");
  56         convertIntegerToString(AddressOf(stringToBePrinted[0]) +
  57                                    strlen(AddressOf(stringToBePrinted[0])),
  58                                i);
  59         strcat(AddressOf(stringToBePrinted[0]), "\n");
  60         printString(AddressOf(stringToBePrinted[0]));
  61       }
  62       EndIf;
  63       Return AddressOf(treeNodes[i]);
  64     }
  65     EndIf;
  66     i += 1;
  67   }
  68   EndWhile;
  69   noMoreFreeMemory();
  70 }
  71 EndFunction;
  72 
  73 Function freeTreeNode(PointerToTreeNode treeNode) Which Returns Nothing Does {
  74   If not(isTreeNodeWithinBounds(treeNode)) Then { segmentationFault(); }
  75   EndIf;
  76   If NDEBUG = 0 Then {
  77     Character stringToBePrinted[64] : = {0};
  78     strcat(AddressOf(stringToBePrinted[0]), "NDEBUG: Freeing the TreeNode #");
  79     convertIntegerToString(AddressOf(stringToBePrinted[0]) +
  80                                strlen(AddressOf(stringToBePrinted[0])),
  81                            (treeNode - AddressOf(treeNodes[0])) /
  82                                SizeOf(TreeNode));
  83     strcat(AddressOf(stringToBePrinted[0]), "\n");
  84     printString(AddressOf(stringToBePrinted[0]));
  85   }
  86   EndIf;
  87   isTreeNodeUsed[(treeNode - AddressOf(treeNodes[0])) / SizeOf(TreeNode)] : = 0;
  88 }
  89 EndFunction;
  90 
  91 Function strlen(PointerToCharacter str) Which Returns Integer32 Does {
  92   If str = 0 Then { Return 0; }
  93   EndIf;
  94   Integer32 length : = 0;
  95   While ValueAt(str + length) Loop { length += 1; }
  96   EndWhile;
  97   Return length;
  98 }
  99 EndFunction;
 100 
 101 Function strncmp(PointerToCharacter first, PointerToCharacter second,
 102                  Integer32 n) Which Returns Integer32 Does {
 103   If first = 0 or second = 0 Then { Return 1; }
 104   EndIf;
 105   Integer32 iterator : = 0;
 106   While iterator < n Loop {
 107     If ValueAt(first + iterator) = ValueAt(second + iterator) Then {
 108       iterator += 1;
 109     }
 110     Else { Return ValueAt(first + iterator) - ValueAt(second + iterator); }
 111     EndIf;
 112   }
 113   EndWhile;
 114   Return 0;
 115 }
 116 EndFunction;
 117 
 118 Function strcpy(PointerToCharacter dest,
 119                 PointerToCharacter src) Which Returns Nothing Does {
 120   While ValueAt(src) Loop {
 121     ValueAt(dest) : = ValueAt(src);
 122     dest += 1;
 123     src += 1;
 124   }
 125   EndWhile;
 126   ValueAt(dest) : = 0;
 127 }
 128 EndFunction;
 129 
 130 Function strcat(PointerToCharacter dest,
 131                 PointerToCharacter src) Which Returns Nothing Does {
 132   strcpy(dest + strlen(dest), src);
 133 }
 134 EndFunction;
 135 
 136 Function reverseString(PointerToCharacter string) Which Returns Nothing Does {
 137   PointerToCharacter pointerToLastCharacter : = string + strlen(string) - 1;
 138   While pointerToLastCharacter - string > 0 Loop {
 139     Character tmp : = ValueAt(string);
 140     ValueAt(string) : = ValueAt(pointerToLastCharacter);
 141     ValueAt(pointerToLastCharacter) : = tmp;
 142     string += 1;
 143     pointerToLastCharacter -= 1;
 144   }
 145   EndWhile;
 146 }
 147 EndFunction;
 148 
 149 Function convertIntegerToString(PointerToCharacter string,
 150                                 Integer32 number) Which Returns Nothing Does {
 151   Integer32 isNumberNegative : = 0;
 152   If number < 0 Then {
 153   number:
 154     = -number;
 155   isNumberNegative:
 156     = 1;
 157   }
 158   EndIf;
 159   Integer32 i : = 0;
 160   While number >= 10 Loop {
 161     ValueAt(string + i) : = '0' + mod(number, 10);
 162     number /= 10;
 163     i += 1;
 164   }
 165   EndWhile;
 166   ValueAt(string + i) : = '0' + number;
 167   i += 1;
 168   If isNumberNegative Then {
 169     ValueAt(string + i) : = '-';
 170     i += 1;
 171   }
 172   EndIf;
 173   ValueAt(string + i) : = 0;
 174   reverseString(string);
 175 }
 176 EndFunction;
 177 
 178 Function convertDecimalToString(PointerToCharacter string,
 179                                 Decimal32 number) Which Returns Nothing Does {
 180   convertIntegerToString(string, number);
 181   number -= Integer32(number);
 182   If number < 0 Then { number *= -1; }
 183   EndIf;
 184   If number = 0 Then { Return; }
 185   EndIf;
 186   strcat(string, ".");
 187   Integer16 numberOfDecimals : = 0;
 188   While numberOfDecimals<3 and number> 0 Loop {
 189     numberOfDecimals += 1;
 190     number *= 10;
 191     Character stringWithTheNewDigit[2];
 192     stringWithTheNewDigit[0] : = stringWithTheNewDigit[1] : = 0;
 193     stringWithTheNewDigit[0] : = '0' + number;
 194     strcat(string, AddressOf(stringWithTheNewDigit[0]));
 195     number -= Integer32(number);
 196   }
 197   EndWhile;
 198 }
 199 EndFunction;
 200 
 201 PointerToCharacter mapOfCodes[256];
 202 
 203 Function assignCode(PointerToCharacter currentCode,
 204                     PointerToTreeNode treeNode) Which Returns Nothing Does {
 205   If NDEBUG = 0 Then {
 206     Character stringToBePrinted[64] : = {0};
 207     strcat(AddressOf(stringToBePrinted[0]), "NDEBUG: Assigning the code \"");
 208     strcat(AddressOf(stringToBePrinted[0]), currentCode);
 209     strcat(AddressOf(stringToBePrinted[0]), "\" to the TreeNode #");
 210     convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 211                                strlen(AddressOf(stringToBePrinted[0])),
 212                            (treeNode - AddressOf(treeNodes[0])) /
 213                                SizeOf(TreeNode));
 214     strcat(AddressOf(stringToBePrinted[0]), ".\n");
 215     printString(AddressOf(stringToBePrinted[0]));
 216 
 217     stringToBePrinted[0] : = 0;
 218     strcat(AddressOf(stringToBePrinted[0]),
 219            "NDEBUG: Its left child is the TreeNode #");
 220     If treeNode->leftChild Then {
 221       convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 222                                  strlen(AddressOf(stringToBePrinted[0])),
 223                              (treeNode->leftChild - AddressOf(treeNodes[0])) /
 224                                  SizeOf(TreeNode));
 225     }
 226     Else { strcat(AddressOf(stringToBePrinted[0]), "null"); }
 227     EndIf;
 228     strcat(AddressOf(stringToBePrinted[0]), ".\n");
 229     printString(AddressOf(stringToBePrinted[0]));
 230 
 231     stringToBePrinted[0] : = 0;
 232     strcat(AddressOf(stringToBePrinted[0]),
 233            "NDEBUG: Its right child is the TreeNode #");
 234     If treeNode->leftChild Then {
 235       convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 236                                  strlen(AddressOf(stringToBePrinted[0])),
 237                              (treeNode->rightChild - AddressOf(treeNodes[0])) /
 238                                  SizeOf(TreeNode));
 239     }
 240     Else { strcat(AddressOf(stringToBePrinted[0]), "null"); }
 241     EndIf;
 242     strcat(AddressOf(stringToBePrinted[0]), ".\n");
 243     printString(AddressOf(stringToBePrinted[0]));
 244   }
 245   EndIf;
 246 
 247   If not(isTreeNodeWithinBounds(treeNode)) Then { segmentationFault(); }
 248   EndIf;
 249 
 250   strcpy(AddressOf(treeNode->code[0]), currentCode);
 251 
 252   Character leftCode[16] : = {0}, rightCode[16] : = {0};
 253 
 254   strcpy(AddressOf(leftCode[0]), currentCode);
 255   strcat(AddressOf(leftCode[0]), "0");
 256   strcpy(AddressOf(rightCode[0]), currentCode);
 257   strcat(AddressOf(rightCode[0]), "1");
 258 
 259   If treeNode->leftChild Then {
 260     assignCode(AddressOf(leftCode[0]), treeNode->leftChild);
 261   }
 262   EndIf;
 263   If treeNode->rightChild Then {
 264     assignCode(AddressOf(rightCode[0]), treeNode->rightChild);
 265   }
 266   EndIf;
 267 
 268   If treeNode->character Then {
 269     mapOfCodes[treeNode->character] : = AddressOf(treeNode->code[0]);
 270     Character codeToPrint[32] : = {0};
 271     codeToPrint[0] : = '\'';
 272     codeToPrint[1] : = treeNode->character;
 273     codeToPrint[2] : = '\'';
 274     codeToPrint[3] : = '=';
 275     codeToPrint[4] : = '>';
 276     codeToPrint[5] : = 0;
 277     strcat(AddressOf(codeToPrint[0]), AddressOf(treeNode->code[0]));
 278     strcat(AddressOf(codeToPrint[0]), "\n");
 279     printString(AddressOf(codeToPrint[0]));
 280   }
 281   EndIf;
 282 }
 283 EndFunction;
 284 
 285 Function freeUpTheTree(PointerToTreeNode tree) Which Returns Nothing Does {
 286   If tree->leftChild Then {
 287     freeUpTheTree(tree->leftChild); // Calling `freeTreeNode` here instead of
 288                                     // `freeUpTheTree` causes a memory leak.
 289   }
 290   EndIf;
 291   If tree->rightChild Then { freeUpTheTree(tree->rightChild); }
 292   EndIf;
 293   freeTreeNode(tree);
 294 }
 295 EndFunction;
 296 
 297 Decimal32 PRECISION : = 500;
 298 Function ln(Decimal32 x) Which Returns Decimal32 Does {
 299   // Natural logarithm is the integral of 1/x from 1 to x, highschool math.
 300   Decimal32 sum : = 0, epsilon : = (x - 1) / (5 * PRECISION), i : = 1;
 301   While(epsilon > 0 and i < x) or (epsilon < 0 and i > x) Loop {
 302     sum += epsilon / i;
 303     i += epsilon;
 304   }
 305   EndWhile;
 306   Return sum;
 307 }
 308 EndFunction;
 309 
 310 Function log2(Decimal32 x) Which Returns Decimal32 Does {
 311   Return ln(x) / ln(2);
 312 }
 313 EndFunction;
 314 
 315 Character input[32];
 316 Character output[256];
 317 
 318 Function getAddressOfTheOutput() Which Returns PointerToCharacter
 319     Does { // To be invoked by the `automaticTest.js` file in the
 320            // `HuffmanCodingInAEC` folder (that file is supposed to be run in
 321            // NodeJS) when the `main` function finishes executing, to compare
 322            // the Huffman coding stored in `output` with the known good
 323            // encodings for test strings.
 324   Return AddressOf(output[0]);
 325 }
 326 EndFunction;
 327 
 328 Function main() Which Returns Nothing Does {
 329   clearScreen();
 330   Integer16 lengthOfInput : = getLengthOfTheInput(), i : = 0;
 331   If NDEBUG = 0 Then {
 332     Character stringToBePrinted[64] : = {0};
 333     strcat(AddressOf(stringToBePrinted[0]),
 334            "NDEBUG: The length of the input is: ");
 335     convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 336                                strlen(AddressOf(stringToBePrinted[0])),
 337                            lengthOfInput);
 338     strcat(AddressOf(stringToBePrinted[0]), "\n");
 339     printString(AddressOf(stringToBePrinted[0]));
 340   }
 341   EndIf;
 342   While i < lengthOfInput Loop {
 343     input[i] : = getCharacterOfTheInput(i);
 344     i += 1;
 345   }
 346   EndWhile;
 347   input[lengthOfInput] : = 0;
 348 
 349   If strlen(AddressOf(input[0])) = 0 Then {
 350     printString("The input is empty!\n");
 351     Return;
 352   }
 353   EndIf;
 354 
 355 i:
 356   = 0;
 357   While i < 256 Loop {
 358     mapOfCodes[i] : = PointerToCharacter(0);
 359     i += 1;
 360   }
 361   EndWhile;
 362 
 363   PointerToTreeNode array[32];
 364   Integer16 lengthOfTheArray : = 0;
 365 i:
 366   = 0;
 367   While i < lengthOfInput Loop {
 368     Integer16 j : = 0, haveWeFoundTheCharacterInTheArray : = 0;
 369     While j < lengthOfTheArray Loop {
 370       If array[j]->character = input[i] Then {
 371       haveWeFoundTheCharacterInTheArray:
 372         = 1;
 373         array[j]->frequencyOfCharacter += 1;
 374       }
 375       EndIf;
 376       j += 1;
 377     }
 378     EndWhile;
 379     If not(haveWeFoundTheCharacterInTheArray) Then {
 380       array[lengthOfTheArray] : = newTreeNode();
 381       array[lengthOfTheArray]->character : = input[i];
 382       array[lengthOfTheArray]->frequencyOfCharacter : = 1;
 383       lengthOfTheArray += 1;
 384     }
 385     EndIf;
 386     i += 1;
 387   }
 388   EndWhile;
 389 
 390 i:
 391   = 0;
 392   While i < lengthOfTheArray Loop {
 393     Character stringToBePrinted[64] : = {0};
 394     strcat(AddressOf(stringToBePrinted[0]), "The character '");
 395     Integer16 indexOfCharacter : = strlen(AddressOf(stringToBePrinted[0]));
 396     stringToBePrinted[indexOfCharacter] : = array[i]->character;
 397     stringToBePrinted[indexOfCharacter + 1] : = 0;
 398     strcat(AddressOf(stringToBePrinted[0]), "' has the frequency of ");
 399     convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 400                                strlen(AddressOf(stringToBePrinted[0])),
 401                            array[i]->frequencyOfCharacter);
 402     strcat(AddressOf(stringToBePrinted[0]), ".\n");
 403     printString(AddressOf(stringToBePrinted[0]));
 404     i += 1;
 405   }
 406   EndWhile;
 407 
 408   Decimal32 ShannonEntropy : = 0;
 409 i:
 410   = 0;
 411   While i < lengthOfTheArray Loop {
 412     ShannonEntropy -=
 413         (array[i]->frequencyOfCharacter / Decimal32(lengthOfInput)) *
 414         log2(array[i]->frequencyOfCharacter / Decimal32(lengthOfInput));
 415     i += 1;
 416   }
 417   EndWhile;
 418   output[0] : = 0;
 419   strcat(AddressOf(output[0]), "The Shannon Entropy of the input string is: ");
 420   convertDecimalToString(AddressOf(output[0]) + strlen(AddressOf(output[0])),
 421                          ShannonEntropy);
 422   strcat(AddressOf(output[0]), " bits/symbol.\n");
 423   printString(AddressOf(output[0]));
 424 
 425   While lengthOfTheArray > 1 Loop {
 426     Integer16 minimum : = 0, secondMinimum : = 0;
 427 
 428     Integer16 i : = 0;
 429     If NDEBUG = 0 Then {
 430       Character stringToBePrinted[64] : = {0};
 431       strcat(AddressOf(stringToBePrinted[0]),
 432              "NDEBUG: The length of the array is ");
 433       convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 434                                  strlen(AddressOf(stringToBePrinted[0])),
 435                              lengthOfTheArray);
 436       strcat(AddressOf(stringToBePrinted[0]), ".\n");
 437       printString(AddressOf(stringToBePrinted[0]));
 438     }
 439     EndIf;
 440     While i < lengthOfTheArray Loop {
 441       If NDEBUG = 0 Then {
 442         Character stringToBePrinted[64] : = {0};
 443         strcat(AddressOf(stringToBePrinted[0]),
 444                "NDEBUG: The tree at the index #");
 445         convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 446                                    strlen(AddressOf(stringToBePrinted[0])),
 447                                i);
 448         strcat(AddressOf(stringToBePrinted[0]), " is the TreeNode #");
 449         convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 450                                    strlen(AddressOf(stringToBePrinted[0])),
 451                                (array[i] - AddressOf(treeNodes[0])) /
 452                                    SizeOf(TreeNode));
 453         strcat(AddressOf(stringToBePrinted[0]), ".\n");
 454         printString(AddressOf(stringToBePrinted[0]));
 455       }
 456       EndIf;
 457       If not(isTreeNodeWithinBounds(array[i])) Then {
 458         segmentationFault();
 459         Return;
 460       }
 461       EndIf;
 462       i += 1;
 463     }
 464     EndWhile;
 465 
 466   i:
 467     = 0;
 468     While i < lengthOfTheArray Loop {
 469       If array[i]->frequencyOfCharacter <
 470           array[minimum]->frequencyOfCharacter Then {
 471       minimum:
 472         = i;
 473       }
 474       EndIf;
 475       i += 1;
 476     }
 477     EndWhile;
 478 
 479   i:
 480     = minimum = 0 ? 1 : 0;
 481   secondMinimum:
 482     = i;
 483     While i < lengthOfTheArray Loop {
 484       If array[i]->frequencyOfCharacter <
 485               array[secondMinimum]->frequencyOfCharacter and
 486           not(i = minimum) Then {
 487       secondMinimum:
 488         = i;
 489       }
 490       EndIf;
 491       i += 1;
 492     }
 493     EndWhile;
 494 
 495     If NDEBUG = 0 Then {
 496       Character stringToBePrinted[64] : = {0};
 497       strcat(AddressOf(stringToBePrinted[0]),
 498              "NDEBUG: The minimum and the second minimum are ");
 499       convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 500                                  strlen(AddressOf(stringToBePrinted[0])),
 501                              minimum);
 502       strcat(AddressOf(stringToBePrinted[0]), " and ");
 503       convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 504                                  strlen(AddressOf(stringToBePrinted[0])),
 505                              secondMinimum);
 506       strcat(AddressOf(stringToBePrinted[0]), ".\n");
 507       printString(AddressOf(stringToBePrinted[0]));
 508     }
 509     EndIf;
 510 
 511     If NDEBUG = 0 Then {
 512       Character stringToBePrinted[64] : = {0};
 513       strcat(AddressOf(stringToBePrinted[0]), "NDEBUG: Joining the TreeNode #");
 514       convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 515                                  strlen(AddressOf(stringToBePrinted[0])),
 516                              (array[minimum] - AddressOf(treeNodes[0])) /
 517                                  SizeOf(TreeNode));
 518       strcat(AddressOf(stringToBePrinted[0]), " with the TreeNode #");
 519       convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 520                                  strlen(AddressOf(stringToBePrinted[0])),
 521                              (array[secondMinimum] - AddressOf(treeNodes[0])) /
 522                                  SizeOf(TreeNode));
 523       strcat(AddressOf(stringToBePrinted[0]), ".\n");
 524       printString(AddressOf(stringToBePrinted[0]));
 525     }
 526     EndIf;
 527 
 528     PointerToTreeNode sumOfTheTwoMostFrequent : = newTreeNode();
 529     sumOfTheTwoMostFrequent->frequencyOfCharacter
 530         : = array[minimum]->frequencyOfCharacter +
 531             array[secondMinimum]->frequencyOfCharacter;
 532     sumOfTheTwoMostFrequent->leftChild : = array[minimum];
 533     sumOfTheTwoMostFrequent->rightChild : = array[secondMinimum];
 534 
 535     If NDEBUG = 0 Then {
 536       Character stringToBePrinted[64] : = {0};
 537       strcat(AddressOf(stringToBePrinted[0]),
 538              "NDEBUG: The new TreeNode has the frequency of: ");
 539       convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 540                                  strlen(AddressOf(stringToBePrinted[0])),
 541                              sumOfTheTwoMostFrequent->frequencyOfCharacter);
 542       strcat(AddressOf(stringToBePrinted[0]), ".\n");
 543       printString(AddressOf(stringToBePrinted[0]));
 544     }
 545     EndIf;
 546 
 547     If not(MAINTAIN_COMPATIBILITY_WITH_JAVASCRIPT_IMPLEMENTATION) Then {
 548       array[minimum] : = sumOfTheTwoMostFrequent;
 549     }
 550     EndIf;
 551 
 552   // Delete the second minimum from the array...
 553   i:
 554     = secondMinimum;
 555     While i < lengthOfTheArray - 1 Loop {
 556       array[i] : = array[i + 1];
 557       i += 1;
 558     }
 559     EndWhile;
 560     lengthOfTheArray -= 1;
 561 
 562     If MAINTAIN_COMPATIBILITY_WITH_JAVASCRIPT_IMPLEMENTATION Then {
 563       // Delete the first minimum from the array...
 564       If minimum >
 565           secondMinimum Then { // If the first minimum moved while we were
 566                                // deleting the second minimum from the array.
 567         minimum -= 1;
 568       }
 569       EndIf;
 570     i:
 571       = minimum;
 572       While i < lengthOfTheArray - 1 Loop {
 573         array[i] : = array[i + 1];
 574         i += 1;
 575       }
 576       EndWhile;
 577       array[lengthOfTheArray - 1] : = sumOfTheTwoMostFrequent;
 578     }
 579     EndIf;
 580   }
 581   EndWhile;
 582 
 583   If NDEBUG = 0 Then {
 584     Character stringToBePrinted[128] : = {0};
 585     strcat(AddressOf(stringToBePrinted[0]),
 586            "NDEBUG: The frequency of the root node is ");
 587     convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 588                                strlen(AddressOf(stringToBePrinted[0])),
 589                            array[0]->frequencyOfCharacter);
 590     strcat(AddressOf(stringToBePrinted[0]),
 591            ". If the algorithm is correctly implemented, it should be ");
 592     convertIntegerToString(AddressOf(stringToBePrinted[0]) +
 593                                strlen(AddressOf(stringToBePrinted[0])),
 594                            lengthOfInput);
 595     strcat(AddressOf(stringToBePrinted[0]), ".\n");
 596     printString(AddressOf(stringToBePrinted[0]));
 597   }
 598   EndIf;
 599 
 600   printString("The tree has been constructed, let us assign Huffman codes to "
 601               "characters:\n");
 602   assignCode("", array[0]);
 603 
 604   Integer16 lengthOfTheOutput : = 0;
 605 i:
 606   = 0;
 607   While i < lengthOfInput Loop {
 608     lengthOfTheOutput += strlen(mapOfCodes[input[i]]);
 609     i += 1;
 610   }
 611   EndWhile;
 612   output[0] : = 0;
 613   strcat(AddressOf(output[0]), "The length of the encoded string is: ");
 614   convertIntegerToString(AddressOf(output[0]) + strlen(AddressOf(output[0])),
 615                          lengthOfTheOutput);
 616   strcat(AddressOf(output[0]), " bits.\n");
 617   printString(AddressOf(output[0]));
 618 
 619   output[0] : = 0;
 620   strcat(AddressOf(output[0]),
 621          "The average length of the symbol in the Huffman code is: ");
 622   convertDecimalToString(AddressOf(output[0]) + strlen(AddressOf(output[0])),
 623                          Decimal32(lengthOfTheOutput) / lengthOfInput);
 624   strcat(AddressOf(output[0]), " bits/symbol.\n");
 625   printString(AddressOf(output[0]));
 626 
 627   output[0] : = 0;
 628 i:
 629   = 0;
 630   While i < lengthOfInput Loop {
 631     strcat(AddressOf(output[0]), mapOfCodes[input[i]]);
 632     i += 1;
 633   }
 634   EndWhile;
 635   strcat(AddressOf(output[0]), "\n");
 636   printString("The Huffman code of the input is:\n");
 637   printString(AddressOf(output[0]));
 638 
 639   freeUpTheTree(array[0]);
 640 
 641   Character stringToBePrinted[64] : = {0};
 642   strcat(AddressOf(stringToBePrinted[0]), "Decoding the output...\n");
 643   printString(AddressOf(stringToBePrinted[0]));
 644 
 645   Integer16 j : = 0;
 646   While j < strlen(AddressOf(output[0])) - 1 Loop {
 647   i:
 648     = 0;
 649     If NDEBUG = 0 Then {
 650       printString(
 651           "NDEBUG: We are entering the loop for decoding the output!\n");
 652     }
 653     EndIf;
 654     While(mapOfCodes[i] = 0 or strncmp(AddressOf(output[j]), mapOfCodes[i],
 655                                        strlen(mapOfCodes[i]))) and
 656         i < 256 Loop {
 657       If NDEBUG = 0 Then {
 658         If mapOfCodes[i] = 0 Then {
 659           printString("NDEBUG: Skipping the character because it's NULL.\n");
 660         }
 661         Else {
 662           printString(
 663               "NDEBUG: Skipping the character because it doesn't match!\n");
 664         }
 665         EndIf;
 666       }
 667       EndIf;
 668       i += 1;
 669     }
 670     EndWhile;
 671     If i = 256 Then {
 672       printString("ERROR: Cannot find the beginning of the current string in "
 673                   "the map of codes!\n");
 674       Return;
 675     }
 676     EndIf;
 677     stringToBePrinted[0] : = 0;
 678     strcat(AddressOf(stringToBePrinted[0]), mapOfCodes[i]);
 679     strcat(AddressOf(stringToBePrinted[0]), "=>");
 680     Character stringToBeAdded[5];
 681     stringToBeAdded[0] : = '\'';
 682     stringToBeAdded[1] : = i;
 683     stringToBeAdded[2] : = '\'';
 684     stringToBeAdded[3] : = '\n';
 685     stringToBeAdded[4] : = 0;
 686     strcat(AddressOf(stringToBePrinted[0]), AddressOf(stringToBeAdded[0]));
 687     printString(AddressOf(stringToBePrinted[0]));
 688     j += strlen(mapOfCodes[i]);
 689   }
 690   EndWhile;
 691 }
 692 EndFunction;
 693