class LZW { class func compress(_ uncompressed:String) -> [Int] { var dict = [String : Int]() for i in 0 ..< 256 { let s = String(Unicode.Scalar(UInt8(i))) dict[s] = i } var dictSize = 256 var w = "" var result = [Int]() for c in uncompressed { let wc = w + String(c) if dict[wc] != nil { w = wc } else { result.append(dict[w]!) dict[wc] = dictSize + 1 w = String(c) } } if w != "" { result.append(dict[w]!) } return result } class func decompress(_ compressed:[Int]) -> String? { var dict = [Int : String]() for i in 0 ..< 256 { dict[i] = String(Unicode.Scalar(UInt8(i))) } var dictSize = 256 var w = String(Unicode.Scalar(UInt8(compressed[0]))) var result = w for k in compressed[1 ..< compressed.count] { let entry : String if let x = dict[k] { entry = x } else if k == dictSize { entry = w + String(w[w.startIndex]) } else { return nil } result += entry dict[dictSize+1] = w + String(entry[entry.startIndex]) w = entry } return result } } let comp = LZW.compress("TOBEORNOTTOBEORTOBEORNOT") print(comp) if let decomp = LZW.decompress(comp) { print(decomp) }