Guest User

LZW Compression

a guest
Feb 4th, 2016
917
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 1.68 KB | None | 0 0
  1. local let=" !#$%&'\"()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
  2. local dict,dlen=let,#let
  3. do local t={}for x in let:gmatch'.'do t[x]=#t t[#t+1]=x end let=t end
  4. function short(n)local s=''repeat s,n=let[n%dlen+1]..s,math.floor(n/dlen)until n==0 return s end
  5. function long(n)local r=0 for i=1,#n do r=r+dlen^(i-1)*let[n:sub(-i,-i)]end return r end
  6.  
  7. function compress(text)
  8.     local dict=dict
  9.     do local t={}for x in dict:gmatch'.'do t[#t+1]=x t[x]=#t end dict=t end
  10.     local s,result='',{}
  11.     for c in text:gmatch'.'do
  12.         local x=s..c
  13.         if dict[x]then
  14.             s=x
  15.         else
  16.             result[#result+1]=dict[s]
  17.             dict[x]=#dict+1
  18.             s=c
  19.         end
  20.     end
  21.     result[#result+1]=dict[s]
  22.     local width,r=1
  23.     for i,v in ipairs(result)do
  24.         r=short(v)
  25.         if #r>width then width=#r end
  26.         result[i]=r
  27.     end
  28.     if width>1 then
  29.         for i,v in ipairs(result)do
  30.             result[i]=(' '):rep(width-#v)..v
  31.         end
  32.     end
  33.     return width..'|'..table.concat(result)
  34. end
  35.  
  36. function decompress(text)
  37.     local dict=dict
  38.     do local t={}for x in dict:gmatch'.'do t[#t+1]=x t[x]=#t end dict=t end
  39.     local data,width,text={},text:match("(%d+)|(.*)")
  40.     for c in text:gmatch(('.'):rep(width))do data[#data+1]=long(c)end
  41.     local prev,curr,entry=data[1]
  42.     local result={dict[prev]}
  43.     for i=2,#data do
  44.         curr=data[i]
  45.         entry=dict[curr]
  46.         if entry then
  47.             result[i]=entry
  48.             dict[#dict+1]=dict[prev]..entry:sub(1,1)
  49.         else
  50.             result[i]=dict[prev]..dict[prev]:sub(1,1)
  51.             dict[#dict+1]=result[i]
  52.         end
  53.         prev=curr
  54.     end
  55.     return table.concat(result)
  56. end
  57.  
  58. local a=[=[long example text]=]
  59.  
  60. local b=compress(a)
  61. print(#a,#b,#a-#b,(#a-#b)*100/#a)
  62. print(b:sub(1,200))
  63. print(decompress(b)==a)
  64. print(os.clock())
Add Comment
Please, Sign In to add comment