public void TestCondenser(int maxChars, int minChars = 0, char minChar = ' ', char maxChar = '~')
        {
            var dict  = HuffmanTreeTests.NumberCharacterGenerator(minChars, maxChars, minChar, maxChar);
            var w     = HuffmanTreeTests.GenerateString(dict);
            var total = HuffmanTreeTests.Total(dict);

            var          condenser      = new SingleCondenser();
            var          condenseOutput = "";
            HuffmanChain chain          = null;

            Assert.DoesNotThrow(() => {
                (string w, HuffmanChain c)valueTuple = condenser.Condense(w);
                condenseOutput = valueTuple.w;
                chain          = valueTuple.c;
            });


            Assert.LessOrEqual(condenseOutput.Length, w.Length);

            Assert.NotNull(chain);

            var expander = new SingleExpander();
            var expanded = expander.Expand(condenseOutput, chain, total);


            Assert.AreEqual(w, expanded);

            TestContext.WriteLine(
                $"Chain Overall Efficiency: cW/w = {(double) condenseOutput.Length / w.Length:P} size decrease");
            TestContext.WriteLine();
        }
        public string Expand(string w, HuffmanChain chain, long totalchars)
        {
            var bOS          = new BitOutputStream(w);
            var bools        = new Queue <bool>(bOS);
            var builder      = new StringBuilder();
            var previousChar = '\0';

            for (long i = 0; i < totalchars; i++)
            {
                var path     = new StringBuilder();
                var added    = false;
                var maxDepth = i == 0 ? chain.MaxDepth() : chain.MaxDepth(previousChar);

                var charToAdd = '\0';

                if (maxDepth == 0)
                {
                    if (i == 0)
                    {
                        added = chain.TryGet("", out charToAdd);
                    }
                    else
                    {
                        added = chain.TryGet("", previousChar, out charToAdd);
                    }
                }

                while (!added)
                {
                    path.Append(bools.Dequeue() ? '1' : '0');

                    if (path.Length > maxDepth)
                    {
                        throw new Exception("Invalid Path");
                    }

                    if (i == 0)
                    {
                        added = chain.TryGet(path.ToString(), out charToAdd);
                    }
                    else
                    {
                        added = chain.TryGet(path.ToString(), previousChar, out charToAdd);
                    }
                }

                builder.Append(charToAdd);
                previousChar = charToAdd;
            }


            return(builder.ToString());
        }
        public void ChainReproductability(int maxChars, int minChars = 0, char minChar = ' ', char maxChar = '~')
        {
            var dict  = HuffmanTreeTests.NumberCharacterGenerator(minChars, maxChars, minChar, maxChar);
            var w     = HuffmanTreeTests.GenerateString(dict);
            var chain = new HuffmanChain(w);


            var output = chain.ToString();

            TestContext.WriteLine("Original: " + output);
            var recreated = HuffmanChain.Reconstruct(output);

            var recreatedString = chain.ToString();

            TestContext.WriteLine("Recreated: " + recreatedString);

            Assert.AreEqual(output, recreatedString);
            Assert.IsTrue(chain.Equals(recreated));
        }
        public void ChainReproductabilityFromFile(string path)
        {
            var w     = File.ReadAllText(path);
            var chain = new HuffmanChain(w);

            var chainOutputService = new HuffmanChain.HuffmanChainOutputService();
            var chainInputService  = new HuffmanChain.HuffmanChainInputService();

            var output = chainOutputService.CreateOutput(chain);

            TestContext.WriteLine("Original: " + output);
            var recreated = chainInputService.CreateFromInput(output);

            var recreatedString = chainOutputService.CreateOutput(recreated);

            TestContext.WriteLine("Recreated: " + recreatedString);

            Assert.AreEqual(output, recreatedString);
            Assert.IsTrue(chain.Equals(recreated));
        }