         }
         self.lengths = newLengths.sorted()
 
-        self.minBits = 16
-        self.maxBits = -1
-
-        self.populateHuffmanSymbols()
-        self.minMaxBits()
-    }
-
-    private mutating func populateHuffmanSymbols() {
-        // Auxiliarly subfunction, which computes reversed order of bits in a number
+        // Calculates symbols for all lengths in the table
         func reverse(bits: Int, in symbol: Int) -> Int {
+            // Auxiliarly subfunction, which computes reversed order of bits in a number
             // This is some weird magic
             var a = 1 << 0
             var b = 1 << (bits - 1)


import Foundation

struct HuffmanTable: CustomStringConvertible {

    var lengths: [HuffmanLength]



        // Calculates symbol and reversedSymbol properties for each length in 'lengths' array
        // This is done with the help of some weird magic
        var loopBits = -1
        var symbol = -1
        for index in 0..<self.lengths.count {
            symbol += 1
            let length = self.lengths[index]
            if length.bits != loopBits {
                symbol <<= (length.bits - loopBits)
                loopBits = length.bits
            }
            self.lengths[index].symbol = symbol
            self.lengths[index].reversedSymbol = reverse(bits: loopBits, in: symbol)
        }

        // Finds minimum and maximum bits in the entire table of lengths
        (self.minBits, self.maxBits) = self.lengths.reduce((16, -1)) {
            return (min($0.0, $1.bits), max($0.1, $1.bits))
        }
    }

}

class OrderedHuffmanTable: HuffmanTable {
    init(arrayOfLenghts: [Int]) {
        var addedLengths = arrayOfLenghts
        addedLengths.append(-1)
        let lengthsCount = addedLengths.count
        let range = Array(0...lengthsCount)
        let bootstrap = (zip(range, addedLengths)).map { [$0, $1] }
        super.init(bootstrap: bootstrap)
    }
}

struct HuffmanLength: Comparable, CustomStringConvertible {
