private static bool TestBuildHuffmanCode(Dictionary<char, double> charFrequency, Dictionary<char, string> huffmanCodeCorrect) { bool testPassed = true; HuffmanTree test = new HuffmanTree(charFrequency); var huffmanCodeGenerated = test.dict; string pool = ""; foreach (KeyValuePair<char, string> kvp in huffmanCodeCorrect) { pool += kvp.Key; } foreach (char s in pool) { Console.WriteLine(s + "\t" + huffmanCodeGenerated[s] + "\t==\t" + s + "\t" + huffmanCodeCorrect[s]); if (huffmanCodeGenerated[s] != huffmanCodeCorrect[s]) testPassed = false; } if (testPassed) Console.WriteLine("Test: Passed.\n"); else Console.WriteLine("Test: Failed."); return testPassed; }
static void Main(string[] args) { if (args.Length < 1 || args[0] == string.Empty) { Console.WriteLine("Please specify an input parameter."); return; } var orig = args[0]; var hf = new HuffmanTree() .Build(orig); var encoded = hf.Encode(orig); var decoded = hf.Decode(encoded); Console.WriteLine($"Original message: {orig}"); Console.WriteLine($"Encoded message: {encoded.ToBinaryString()}"); Console.WriteLine($"Decoded message: {decoded}"); hf.Root.Print(); }
static void importfromfileTest(string[] args) { Dictionary<char, int> zeichentabelle; Dictionary<char, double> relativeAnzahl; string file = args[0]; string text = ""; try { text = Dictcreator.getInput(file); } catch (Exception e) { Console.WriteLine(e.Message); } zeichentabelle = Dictcreator.createDictionaryFromString(text); relativeAnzahl = Dictcreator.getRelativeFrequencyDict(zeichentabelle); HuffmanTree tree = new HuffmanTree(relativeAnzahl); tree.printTree(tree.root); }
// this method creates a tree based on text public static HuffmanTree CreateFromText(string text) { // the list that we wanna fill up with nodes List <HuffmanNode> nodeList = new List <HuffmanNode>(); // all the characters from the text char[] characters = text.ToCharArray(); // loop thought the characters for (int i = 0; i < characters.Length; i++) { // the character as a string string read = characters[i].ToString(); // has the node already been created? if (nodeList.Exists(x => x.Symbol == read)) { // If is yes, find the index of the Node and increase the frequency of the Node. nodeList[nodeList.FindIndex(y => y.Symbol == read)].Frequency++; } else { // If is no, create a new node and add to the List of Nodes nodeList.Add(new HuffmanNode(read)); } } // sort them, this is done based on frequency because of IComparable<HuffmanNode>.CompareTo nodeList.Sort(); // loop thought them, until only one is left while (nodeList.Count > 1) { // Get the node of the first index of List, this is the one with the lowest frequency HuffmanNode node1 = nodeList[0]; // and delete it. nodeList.RemoveAt(0); // do the same thing again HuffmanNode node2 = nodeList[0]; nodeList.RemoveAt(0); // make a parant node with node1 and node2 and the left and right child nodes nodeList.Add(new HuffmanNode(node1, node2)); // and sort it again according to frequency. nodeList.Sort(); } // create a tree based on the remaining root node HuffmanTree tree = new HuffmanTree(nodeList[0]); // this is a recursive function to set the binary code of every leaf node void setCodeToTheTree(HuffmanNode Nodes, BitArray code = null) { // if the current code is not set, set it to an empty BitArray if (code == null) { code = new BitArray(new bool[] { }); } // if the code is empty do nothing if (Nodes == null) { return; } // if there is no left node and right node, then set the code based on the current code if (Nodes.LeftChildNode == null && Nodes.RightChildNode == null) { Nodes.Code = code; return; } // create a bitlist for the left node BitList left = BitList.Parse(code); // add false for the left side left.Add(false); // call this function recursively, with the left bitlist and the left side node setCodeToTheTree(Nodes.LeftChildNode, left.ToBitArray()); // create a bitlist for the right node BitList right = BitList.Parse(code); // add true for the right side right.Add(true); // call the function recursively, with the right bitlist and the right side node setCodeToTheTree(Nodes.RightChildNode, right.ToBitArray()); } // call the recursive function setCodeToTheTree(tree.Root); // the tree return(tree); }
static void Main(string[] args) { HuffmanTree.EncodingType = Encoding.UTF8; List <Article> articles = new List <Article> { new Article() { title = "den danske grundlov", extract = SomeRandomText.DenDanskeGrundlov }, new Article() { title = "mini srp infohæfte 2018", extract = File.ReadAllText(@"E:\Libraries\Documents\Visual Studio 2017\Projects\huffman\huffman\MiniSRPinfohæfte2018.txt") }, new Article() { title = "euklids elementer", extract = File.ReadAllText(@"E:\Libraries\Documents\Visual Studio 2017\Projects\huffman\huffman\EuklidsElementer.txt") } }; if (Directory.Exists(OUTPUT_DIR)) { Directory.Delete(OUTPUT_DIR, true); } var outputDir = Directory.CreateDirectory(OUTPUT_DIR); foreach (var article in articles) { var tree = HuffmanTree.CreateFromText(article.extract); var subDir = outputDir.CreateSubdirectory(article.title); var treeFilePath = Path.Combine(subDir.FullName, "tree.json"); File.Create(treeFilePath).Close(); File.WriteAllText(treeFilePath, tree.JSONEncode()); var originalFilePath = Path.Combine(subDir.FullName, "original.txt"); File.Create(originalFilePath).Close(); File.WriteAllText(originalFilePath, article.extract); var encodedFilePath = Path.Combine(subDir.FullName, "encoded.txt"); File.Create(encodedFilePath).Close(); var encodedData = tree.Encode(article.extract); File.WriteAllBytes(encodedFilePath, encodedData); var encodedReadAbleFilePath = Path.Combine(subDir.FullName, "encoded_readable.txt"); File.Create(encodedReadAbleFilePath).Close(); File.WriteAllText(encodedReadAbleFilePath, (new BitArray(encodedData)).Print()); var decodedFilePath = Path.Combine(subDir.FullName, "decoded.txt"); File.Create(decodedFilePath).Close(); var decodedData = tree.Decode(encodedData); File.WriteAllText(decodedFilePath, decodedData); var statsFilePath = Path.Combine(subDir.FullName, "stats.txt"); File.Create(statsFilePath).Close(); File.WriteAllLines(statsFilePath, new string[] { "original size: " + (article.extract.Length * 8) + " b", "compressed size: " + encodedData.Length + " b", "compression percentage: " + (100 * ((double)encodedData.Length / ((double)HuffmanTree.EncodingType.GetBytes(article.extract).Length))) + "%", "tree size as json: " + (HuffmanTree.EncodingType.GetBytes(tree.JSONEncode()).Length) + " b", "tree size as bytes: " + (new Func <string>(() => { byte[] bytes; IFormatter formatter = new BinaryFormatter(); using (MemoryStream stream = new MemoryStream()){ formatter.Serialize(stream, tree); bytes = stream.ToArray(); } return("" + bytes.Length); }))() + " b", "lossness: " + (article.extract == decodedData ? "yes" : (new Func <string>(() => { string re = "no" + Environment.NewLine; if (article.extract.Length == decodedData.Length) { List <string> errors = new List <string>(); for (int i = 0; i < article.extract.Length; i++) { if (article.extract[i] != decodedData[i]) { errors.Add("position " + i + " does not match; original: " + article.extract[i].ToString() + ", decoded: " + decodedData[i].ToString()); } } re += String.Join(Environment.NewLine, errors.ToArray()); } else { re += "not the same length; original: " + article.extract.Length + ", decoded: " + decodedData.Length; } return(re); }))()) }); } Console.WriteLine("Done"); Thread.Sleep(-1); }
// this method creates a tree based on text // Denne funktion laver et træ baseret på tekst public static HuffmanTree CreateFromText(string text) { // the list that we wanna fill up with nodes // Listen der skal fyldes med noder List <HuffmanNode> nodeList = new List <HuffmanNode>(); // all the characters from the text // Alle symbolerne fra teksten char[] characters = text.ToCharArray(); // loop thought the characters // Gentag igennem symbolerne for (int i = 0; i < characters.Length; i++) { // the character as a string // Symbolerne som strenge string read = characters[i].ToString(); // has the node already been created? // Er noden allerede blevet skabt? if (nodeList.Exists(x => x.Symbol == read)) { // If is yes, find the index of the Node and increase the frequency of the Node. // Hvis ja, find indekset for noden og øg frekvensen for node nodeList[nodeList.FindIndex(y => y.Symbol == read)].Frequency++; } else { // If is no, create a new node and add to the List of Nodes // Hvis nej, skab en ny node og tilføj den til listen over node nodeList.Add(new HuffmanNode(read)); } } // sort them, this is done based on frequency because of IComparable<HuffmanNode>.CompareTo // Sorter dem, dette gøres baseret på frekvens fordi at IComparable<HuffmanNode>.CompareTo nodeList.Sort(); // loop thought them, until only one is left // Kør igennem dem alle sammen indtil der kun er en tilbage while (nodeList.Count > 1) { // Get the node of the first index of List, this is the one with the lowest frequency // Få noden for det første indeks af Listen, dette er den med den laveste frekvens HuffmanNode node1 = nodeList[0]; // and delete it. // Fjern den nodeList.RemoveAt(0); // do the same thing again // Gør det samme igen HuffmanNode node2 = nodeList[0]; nodeList.RemoveAt(0); // make a parant node with node1 and node2 and the left and right child nodes // Lav en parent-node med node1 og node1 og de venstre og højre child-noder nodeList.Add(new HuffmanNode(node1, node2)); // and sort it again according to frequency. // Og sorter det igen efter frekvens nodeList.Sort(); } // create a tree based on the remaining root node // Lav et træ baseret på den tilbageværende rod-node HuffmanTree tree = new HuffmanTree(nodeList[0]); // this is a recursive function to set the binary code of every leaf node // Dette er en rekursiv funktion for at sætte den binære værdi for hvert blad void setCodeToTheTree(HuffmanNode Nodes, BitArray code = null) { // if the current code is not set, set it to an empty BitArray // Hvis den nuværende kode ikke er sat, sættes den til et tomt BitArray if (code == null) { code = new BitArray(new bool[] { }); } // if the code is empty do nothing // Hvis koden er tom, gør intet if (Nodes == null) { return; } // if there is no left node and right node, then set the code based on the current code // Hvis der ikke er nogen venstre node, sæt koden baseret på den nuværende kode if (Nodes.LeftChildNode == null && Nodes.RightChildNode == null) { Nodes.Code = code; return; } // create a bitlist for the left node // lav en bitliste for den venstre node BitList left = BitList.Parse(code); // add false for the left side // tilføj false for den venstre side left.Add(false); // call this function recursively, with the left bitlist and the left side node // Kald denne funktion rekursivt, med den venstre bitliste og den venstre node setCodeToTheTree(Nodes.LeftChildNode, left.ToBitArray()); // create a bitlist for the right node // Lav en bitliste for den højre node BitList right = BitList.Parse(code); // add true for the right side // tilføj true for den højre side right.Add(true); // call the function recursively, with the right bitlist and the right side node // Kald denne funktion rekursivt, med den højre bitliste og den højre node setCodeToTheTree(Nodes.RightChildNode, right.ToBitArray()); } // call the recursive function // Kald den rekursive funktion setCodeToTheTree(tree.Root); // the tree // Træet returneres return(tree); }