LZW compression: Difference between revisions

Applesoft BASIC
m (→‎version 2: changed data era to be more PC, added/changed comments and whitespace, added continuation indicator.)
(Applesoft BASIC)
 
(32 intermediate revisions by 18 users not shown)
Line 8:
=={{header|11l}}==
{{trans|Python}}
<langsyntaxhighlight lang="11l">F compress(uncompressed)
V dict_size = 256
V dictionary = Dict((0 .< dict_size).map(i -> (String(Char(code' i)), i)))
Line 51:
V compressed = compress(‘TOBEORNOTTOBEORTOBEORNOT’)
print(compressed)
print(decompress(&compressed))</langsyntaxhighlight>
 
=={{header|Ada}}==
Line 57:
 
lzw.ads:
<langsyntaxhighlight Adalang="ada">package LZW is
 
MAX_CODE : constant := 4095;
Line 67:
function Decompress (Data : in Compressed_Data) return String;
 
end LZW;</langsyntaxhighlight>
 
lzw.adb:
<langsyntaxhighlight Adalang="ada">with Ada.Containers.Ordered_Maps;
with Ada.Strings.Unbounded;
 
Line 185:
end Decompress;
 
end LZW;</langsyntaxhighlight>
 
test.adb:
<langsyntaxhighlight Adalang="ada">with LZW;
with Ada.Text_IO;
 
Line 208:
Text_IO.Put_Line (Cleartext);
end;
end Test;</langsyntaxhighlight>
 
=={{header|Applesoft BASIC}}==
{{trans|BBC BASIC}}
<syntaxhighlight lang="BASIC"> 0 PLAIN$ = "TOBEORNOTTOBEORTOBEORNOT"
10 GOSUB 200"ENCODE PLAIN$
20 FOR I = 1 TO LEN (ENCODE$) STEP 2
30 PRINT S$ ASC ( MID$ (ENCODE$,I)) + 256 * ASC ( MID$ (ENCODE$,I + 1));
40 LET S$ = " "
50 NEXT
60 PRINT
70 GOSUB 300"DECODE ENCODE$
80 PRINT PLAIN$;
90 END
 
100 FOR C = 0 TO 1E9 STEP 0
110 IF I > S THEN RETURN
120 FOR D = 1 TO L - 1
130 IF W$ < > DICT$(D) THEN NEXT D
140 IF D > = L THEN RETURN
150 LET I = I + 1
160 LET W$ = W$ + MID$ (PLAIN$,I,1)
170 LET C = D
180 NEXT C
190 RETURN
 
REM ENCODE PLAIN$ RETURN ENCODE$
200 IF NOT DI THEN DIM DICT$(4095)
210 FOR I = 0 TO 255:DICT$(I) = CHR$ (I): NEXT
220 LET DI = 1 : L = I : S = LEN (PLAIN$):ENCODE$ = ""
230 LET W$ = LEFT$ (PLAIN$,1)
240 FOR I = 1 TO 1E9 STEP 0
250 GOSUB 100
260 LET DICT$(L) = W$:L = L + 1:W$ = RIGHT$ (W$,1)
270 LET C% = C / 256:ENCODE$ = ENCODE$ + CHR$ (C - C% * 256) + CHR$ (C%)
280 IF I < = S THEN NEXT I
290 RETURN
 
REM DECODE ENCODE$ RETURN PLAIN$
300 IF NOT DI THEN DIM DICT$(4095)
310 FOR I = 0 TO 255:DICT$(I) = CHR$ (I): NEXT
320 LET DI = 1 : L = I
330 FOR I = L TO 4095:DICT$(I) = "": NEXT
340 LET C = ASC (ENCODE$) + 256 * ASC ( MID$ (ENCODE$,2))
350 LET W$ = DICT$(C)
360 LET PLAIN$ = W$
370 LET S = LEN (ENCODE$)
380 IF S < 4 THEN RETURN
400 FOR I = 3 TO S STEP 2
410 LET C = ASC ( MID$ (ENCODE$,I)) + 256 * ASC ( MID$ (ENCODE$,I + 1))
420 IF C < L THEN T$ = DICT$(C)
430 IF C > = L THEN T$ = W$ + LEFT$ (W$,1)
440 LET PLAIN$ = PLAIN$ + T$
450 LET DICT$(L) = W$ + LEFT$ (T$,1)
460 LET L = L + 1
470 LET W$ = T$
480 NEXT
490 RETURN</syntaxhighlight>
{{out}}
<pre>84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263
TOBEORNOTTOBEORTOBEORNOT</pre>
 
=={{header|AWK}}==
copy the following to standard input
<syntaxhighlight>
==comp
TOBEORNOTTOBEORTOBEORNOT
To be or not to be that is the question!
"There is nothing permanent except change." --- Heraclitus [540 -- 475 BCE]
 
==decomp
84,79,66,69,79,82,78,79,84,256,258,260,265,259,261,263
84,111,32,98,101,32,111,114,32,110,111,116,32,116,257,259,268,104,97,267,105,115,272,260,113,117,101,115,116,105,111,110,33
34,84,104,101,114,101,32,105,115,32,110,111,116,104,105,110,103,32,112,259,109,97,110,101,110,116,32,101,120,99,101,112,281,99,104,277,103,101,46,34,32,296,45,298,296,32,72,259,97,99,108,105,116,117,264,32,91,53,52,48,32,299,52,55,53,32,66,67,69,93
</syntaxhighlight>
 
<syntaxhighlight lang="AWK">
# ported from Python
BEGIN {
is_comp = 0
is_decomp = 0
}
 
{
if ($0 == "") next
if ($1 == "==comp") {
is_comp = 1
is_decomp = 0
print "\ncompressing..."
next
}
if ($1 == "==decomp") {
is_comp = 0
is_decomp = 1
print "\ndecompressing..."
next
}
if (is_comp) print compress($0)
if (is_decomp) print decompress($0)
}
function compress(str, dict_size, i, dictionary, w, result, len, uncompressed, c, wc ) {
dict_size = 256
for (i = 0; i <= dict_size; i++) dictionary[chr(i)] = i
w = ""
result = ""
len = split(str, uncompressed, "")
for (i = 1; i <= len; i++) {
c = uncompressed[i]
wc = w c
if (wc in dictionary) w = wc
else {
result = result "," dictionary[w]
dictionary[wc] = dict_size++
w = c
}
}
if (length(w)) result = result "," dictionary[w]
return substr(result,2)
return "[" substr(result,2) "]"
}
 
function decompress(str) {
dict_size = 256
for (i = 0; i <= dict_size; i++) dictionary[i] = chr(i)
result = ""
len = split(str, compressed, ",")
w = chr(compressed[1])
result = result w
for (i = 2; i <= len; i++) {
k = compressed[i]
if (k in dictionary) entry = dictionary[k]
else if (k == dict_size) entry = w substr(w,1,1)
else { entry = "*" }
result = result entry
dictionary[dict_size++] = w substr(entry,1,1)
w = entry
}
return result
}
 
function chr(c) {
return sprintf("%c", c + 0)
}</syntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">compress: function [str][
dict: #[]
loop 0..255 'i -> dict\[to :char i]: i
 
w: ""
result: new []
loop str 'c [
wc: w ++ c
if? key? dict wc -> w: wc
else [
'result ++ dict\[w]
dict\[wc]: size dict
w: to :string c
]
]
 
if 0 < size w -> 'result ++ dict\[w]
return result
]
 
 
decompress: function [compressed][
dict: #[]
arr: new compressed
loop 0..255 'i -> dict\[i]: to :string to :char i
 
w: dict\[first arr]
remove 'arr .index 0
 
result: w
loop arr 'k [
entry: ""
if? key? dict k -> entry: dict\[k]
else [
if? k = size dict -> entry: w ++ first w
else -> panic ~"Error with compressed: |k|"
]
'result ++ entry
dict\[size dict]: w ++ first entry
w: entry
]
return result
]
 
compressed: compress "TOBEORNOTTOBEORTOBEORNOT"
print "Compressed:"
print compressed
print ""
 
decompressed: decompress compressed
print "Decompressed:"
print decompressed</syntaxhighlight>
 
{{out}}
 
<pre>Compressed:
84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263
 
Decompressed:
TOBEORNOTOBEORNOTOOBEORTOOBEORNOT</pre>
 
=={{header|BaCon}}==
<langsyntaxhighlight lang="bacon">CONST lzw_data$ = "TOBEORNOTTOBEORTOBEORNOT"
 
PRINT "LZWData: ", lzw_data$
Line 286 ⟶ 498:
RETURN result$
 
END FUNCTION</langsyntaxhighlight>
{{out}}
<pre>LZWData: TOBEORNOTTOBEORTOBEORNOT
Line 296 ⟶ 508:
{{works with|BBC BASIC for Windows}}
Uses fixed bit-width (16 bits) and initial dictionary size = 256.
<langsyntaxhighlight lang="bbcbasic"> plaintext$ = "TOBEORNOTTOBEORTOBEORNOT"
encodeLZW$ = FNencodeLZW(plaintext$)
FOR i% = 1 TO LEN(encodeLZW$) STEP 2
Line 343 ⟶ 555:
w$ = t$
NEXT
= o$</langsyntaxhighlight>
{{out}}
<pre>
Line 358 ⟶ 570:
'''WARNING: This code appears to have come from a GIF codec that has been modified to meet the requirements of this page, provided that the decoder works with the encoder to produce correct output. For writing GIF files the write_bits subroutine is wrong for Little Endian systems (it may be wrong for Big Endian as well.) The encoder also increases the number of bits in the variable length GIF-LZW after the N-2 code, whereas this must be done after N-1 to produce a working GIF file (just looking at the encoder, it's easy to see how this mistake could be made.)'''
 
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 615 ⟶ 827:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp}}==
{{trans|Java}}
<langsyntaxhighlight Clang="c sharp">using System;
using System.Collections.Generic;
using System.Text;
Line 699 ⟶ 911:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 707 ⟶ 919:
=={{header|C++}}==
{{trans|D}}
<langsyntaxhighlight lang="cpp">#include <string>
#include <map>
 
Line 787 ⟶ 999:
return 0;
}</langsyntaxhighlight>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="lisp">(defn make-dict []
(let [vals (range 0 256)]
(zipmap (map (comp #'list #'char) vals) vals)))
Line 808 ⟶ 1,020:
(reverse (if w (cons (get dict w) r) r))))))
 
(compress "TOBEORNOTTOBEORTOBEORNOT")</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="lisp">(84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263)</langsyntaxhighlight>
 
=={{header|CoffeeScript}}==
This only does the encoding step for now.
 
<langsyntaxhighlight lang="coffeescript">
lzw = (s) ->
dct = {} # map substrings to codes between 256 and 4096
Line 852 ⟶ 1,064:
console.log lzw "TOBEORNOTTOBEORTOBEORNOT"
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 884 ⟶ 1,096:
The exact encoding used is dependent upon the user's locale (<code>LC_CTYPE</code> on Unix).
 
<langsyntaxhighlight lang="lisp">(declaim (ftype (function (vector vector &optional fixnum fixnum) vector)
vector-append))
(defun vector-append (old new &optional (start2 0) end2)
Line 993 ⟶ 1,205:
(assert (equal #2=(lzw-decompress-to-string (lzw-compress string)) string) ()
"Can't compress ~S properly, got ~S instead" string #2#)
t)</langsyntaxhighlight>
 
And the format used:
 
<langsyntaxhighlight lang="lisp">CL-USER> (test "TOBEORNOTTOBEORTOBEORNOT")
T
CL-USER> (lzw-compress "TOBEORNOTTOBEORTOBEORNOT")
#(84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263)
CL-USER> (lzw-decompress-to-string *)
"TOBEORNOTTOBEORTOBEORNOT"</langsyntaxhighlight>
 
=={{header|D}}==
===Simpler Version===
<langsyntaxhighlight lang="d">import std.stdio, std.array;
 
auto compress(in string original) pure nothrow {
Line 1,045 ⟶ 1,257:
auto comp = "TOBEORNOTTOBEORTOBEORNOT".compress;
writeln(comp, "\n", comp.decompress);
}</langsyntaxhighlight>
{{out}}
<pre>[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
Line 1,052 ⟶ 1,264:
===More Refined Version===
This longer version is a little more efficient and it uses stronger static typing.
<langsyntaxhighlight lang="d">struct LZW {
import std.array: empty;
 
Line 1,146 ⟶ 1,358:
compressed.writeln;
LZW.decompress(compressed).assumeUTF.writeln;
}</langsyntaxhighlight>
{{out}}
<pre>[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
Line 1,154 ⟶ 1,366:
{{trans|C}}
This code retains part of the style of the original C code.
<langsyntaxhighlight lang="d">enum Marker: ushort {
CLR = 256, // Clear table marker.
EOD = 257, // End-of-data marker.
Line 1,375 ⟶ 1,587:
 
"Decoded OK.".writeln;
}</langsyntaxhighlight>
{{out}}
<pre>Input size: 206403
Line 1,383 ⟶ 1,595:
 
=={{header|Dylan}}==
<langsyntaxhighlight lang="dylan">Module: LZW
Synopsis: LZW implementation for Rosetta code
 
Line 1,425 ⟶ 1,637:
end;
 
format-out("%=\n", compress("TOBEORNOTTOBEORTOBEORNOT"))</langsyntaxhighlight>
 
=={{header|Eiffel}}==
<syntaxhighlight lang="eiffel">
<lang Eiffel>
class
APPLICATION
Line 1,541 ⟶ 1,753:
 
end
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,550 ⟶ 1,762:
=={{header|Elixir}}==
{{trans|Erlang}}
<langsyntaxhighlight lang="elixir">defmodule LZW do
@encode_map Enum.into(0..255, Map.new, &{[&1],&1})
@decode_map Enum.into(0..255, Map.new, &{&1,[&1]})
Line 1,588 ⟶ 1,800:
IO.inspect enc = LZW.encode(str)
IO.inspect dec = LZW.decode(enc)
IO.inspect str == dec</langsyntaxhighlight>
 
{{out}}
Line 1,595 ⟶ 1,807:
"TOBEORNOTTOBEORTOBEORNOT"
true
</pre>
 
=={{header|EMal}}==
<syntaxhighlight lang="emal">
type LzwCompression
fun compress ← List by text uncompressed
List output ← int[]
text working ← Text.EMPTY
Map symbolTable ← text%int[].with(256, <int i|text%int(chr(i) => i))
for each text c in uncompressed
text augmented ← working + c
if symbolTable.has(augmented)
working ← augmented
else
symbolTable.insert(augmented, symbolTable.length)
int i ← symbolTable[working]
output.append(i)
working ← c
end
end
if not working.isEmpty()
int i ← symbolTable[working]
output.append(i)
end
return output
end
fun decompress ← text by List compressed
Map symbolTable ← int%text[].with(256, <int i|int%text(i => chr(i)))
text working ← symbolTable[compressed[0]]
text output ← *working
for each int i in compressed.extract(1)
text s
if symbolTable.has(i)
s ← symbolTable[i]
else if i æ symbolTable.length # cScSc problem
s ← working + working[0]
else
error(65, "Error decompressing")
end
output.append(s)
symbolTable.insert(symbolTable.length, working + s[0])
working ← s
end
return output
end
List compressed = compress("TOBEORNOTTOBEORTOBEORNOT")
writeLine(compressed)
text decompressed = decompress(compressed)
writeLine(decompressed)
</syntaxhighlight>
{{out}}
<pre>
[84,79,66,69,79,82,78,79,84,256,258,260,265,259,261,263]
TOBEORNOTTOBEORTOBEORNOT
</pre>
 
=={{header|Erlang}}==
<langsyntaxhighlight lang="erlang">-module(lzw).
 
-export([test/0, encode/1, decode/1]).
Line 1,654 ⟶ 1,920:
 
init1(0, D) -> D;
init1(N, D) -> D1 = dict:store(N,[N],D), init1(N-1, D1).</langsyntaxhighlight>
 
=={{header|Forth}}==
{{works with|GNU Forth|0.6.2}}
<langsyntaxhighlight lang="forth">256 value next-symbol
 
\ current string fragment
Line 1,756 ⟶ 2,022:
 
out out-size @ decompress cr
\ TOBEORNOTTOBEORTOBEORNOT</langsyntaxhighlight>
 
=={{header|Fortran}}==
<syntaxhighlight lang="fortran">
<lang Fortran>
!
! lzw_shared_parameters.f90
Line 2,181 ⟶ 2,447:
CALL CPU_TIME(finish)
PRINT '("Time = ",f6.3," seconds.")' , finish - start
END PROGRAM MAIN</syntaxhighlight>
 
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' version 22-02-2019
' compile with: fbc -s console
 
Line 2,294 ⟶ 2,558:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
{{out}}
<pre> input str: TOBEORNOTTOBEORTOBEORNOT
Line 2,309 ⟶ 2,573:
not just ASCII or valid UTF8 encoding
(tested with [https://github.com/dvyukov/go-fuzz go-fuzz]).
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,403 ⟶ 2,667:
}
fmt.Println(decompressed)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,411 ⟶ 2,675:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def compress = { text ->
def dictionary = (0..<256).inject([:]) { map, ch -> map."${(char)ch}" = ch; map }
def w = '', compressed = []
Line 2,447 ⟶ 2,711:
 
result.toString()
}</langsyntaxhighlight>
Testing:
<langsyntaxhighlight lang="groovy">def plaintext = 'TOBEORNOTTOBEORTOBEORNOT'
def compressed = compress(plaintext)
def result = decompress(compressed)
Line 2,456 ⟶ 2,720:
Plaintext: '$plaintext'
Compressed: $compressed
Uncompressed: '$result'""".stripIndent()</langsyntaxhighlight>
{{out}}
<pre>Plaintext: 'TOBEORNOTTOBEORTOBEORNOT'
Line 2,464 ⟶ 2,728:
=={{header|Haskell}}==
 
<langsyntaxhighlight Haskelllang="haskell">import Data.List (elemIndex, tails)
import Data.Maybe (fromJust)
 
Line 2,501 ⟶ 2,765:
print $
((==) <*> ((.) <$> undoLZW <*> doLZW) ['\NUL' .. '\255'])
"TOBEORNOTTOBEORTOBEORNOT"</langsyntaxhighlight>
{{Out}}
<pre>[84,79,66,69,79,82,78,79,84,256,258,260,265,259,261,263]
Line 2,512 ⟶ 2,776:
 
Straightforward implementations of encoding and decoding:
<langsyntaxhighlight Jlang="j">encodeLZW =: 4 : 0
d=. ;/x
r=.0$0
Line 2,525 ⟶ 2,789:
end.
r, d i.<w
)</langsyntaxhighlight>
Test:
<pre> a. encodeLZW 'TOBEORNOTTOBEORTOBEORNOT'
84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263</pre>
Decoding:
<langsyntaxhighlight Jlang="j">decodeLZW =: 4 : 0
d=.;/x
w=.r=. >d{~{.y
Line 2,545 ⟶ 2,809:
end.
;r
)</langsyntaxhighlight>
Test:
<pre> a. decodeLZW 84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263
Line 2,563 ⟶ 2,827:
=={{header|Java}}==
{{works with|Java|1.5+}}
<langsyntaxhighlight lang="java5">import java.util.*;
 
public class LZW {
Line 2,629 ⟶ 2,893:
System.out.println(decompressed);
}
}</langsyntaxhighlight>
 
{{out}} (Command Line direct output):
<langsyntaxhighlight lang="java5">[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
TOBEORNOTTOBEORTOBEORNOT</langsyntaxhighlight>
 
=={{header|JavaScript}}==
<langsyntaxhighlight lang="javascript">//LZW Compression/Decompression for Strings
var LZW = {
compress: function (uncompressed) {
Line 2,716 ⟶ 2,980:
comp = LZW.compress("TOBEORNOTTOBEORTOBEORNOT"),
decomp = LZW.decompress(comp);
document.write(comp + '<br>' + decomp);</langsyntaxhighlight>
 
 
Line 2,723 ⟶ 2,987:
This is the the same thing, but for ES6. The code has been refactored and cleaned up a bit to look neater.
 
<langsyntaxhighlight lang="javascript">'use strict';
/**
Namespace for LZW compression and decompression.
Line 2,832 ⟶ 3,096:
 
console.log(`${comp}
${decomp}`);</langsyntaxhighlight>
 
{{out}}
Line 2,841 ⟶ 3,105:
{{ works with|jq|1.4}}
{{trans|JavaScript}}
<langsyntaxhighlight lang="jq"># LZW compression/decompression for strings
def lzw_compress:
def decode: [.] | implode;
Line 2,886 ⟶ 3,150:
| .[2] = $entry # w = entry
) | .[3]
;</langsyntaxhighlight>
'''Example''':
<langsyntaxhighlight lang="jq">"TOBEORNOTTOBEORTOBEORNOT" | lzw_compress| lzw_decompress</langsyntaxhighlight>
{{Out}}
$ jq -n -f LZW.jq
Line 2,895 ⟶ 3,159:
=={{header|Julia}}==
{{works with|Julia|1.1.1}}
<langsyntaxhighlight lang="julia">function compressLZW(decompressed::String)
dictsize = 256
dict = Dict{String,Int}(string(Char(i)) => i for i in 0:dictsize)
Line 2,944 ⟶ 3,208:
comprate = (length(word) - length(comp)) / length(word) * 100
println("Original: $word\n-> Compressed: $comp (compr.rate: $(round(comprate, digits=2))%)\n-> Decompressed: $decomp")
end</langsyntaxhighlight>
 
{{out}}
Line 2,959 ⟶ 3,223:
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.1.2
 
object Lzw {
Line 3,020 ⟶ 3,284:
val decompressed = Lzw.decompress(compressed)
println(decompressed)
}</langsyntaxhighlight>
 
{{out}}
Line 3,033 ⟶ 3,297:
It also has the option to write the encoding/decoding dictionaries to file so the encoder can be checked for accuracy.
This code directly follows the methodology described in an excellent web article by Juha Nieminen entitled "An efficient LZW implementation".
<syntaxhighlight lang="text"> DIM LZW(1, 1)
DIM JDlzw(1)
DIM JDch$(1)
Line 3,312 ⟶ 3,576:
fileTag$ = STR$(tagCount) + "_"
RETURN
''''''''''''''''''''''''''''''''''''''''</langsyntaxhighlight>
 
=={{header|Lua}}==
 
<lang lua>local function compress(uncompressed) -- string
<syntaxhighlight lang="lua">local function compress(uncompressed) -- string
local dictionary, result, dictSize, w, c = {}, {}, 255, ""
for i = 0, 255 do
Line 3,338 ⟶ 3,603:
 
local function decompress(compressed) -- table
local dictionary, dictSize, entry, result, w, k = {}, 0256, "", {}, ""string.char(compressed[1])
local result = {w}
for i = 0, 255 do
dictionary[i] = string.char(i)
end
for i = 12, #compressed do
k = compressed[i]
if dictionary[k] then
Line 3,363 ⟶ 3,629:
local dec = decompress(com)
print(table.concat(com, ", "))
print(dec)</langsyntaxhighlight>
 
{{Out}}
Line 3,373 ⟶ 3,639:
=={{header|M2000 Interpreter}}==
{{trans|BBC BASIC}}
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module BBCtrans {
\\ LZW compression
Line 3,426 ⟶ 3,692:
}
BBCtrans
</syntaxhighlight>
</lang>
 
And here a change for using Inventories, where we have hash function, and we find entry in O(1).
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module FastM2000 {
plaintext$="TOBEORNOTTOBEORTOBEORNOT"
Line 3,487 ⟶ 3,753:
}
FastM2000
</syntaxhighlight>
</lang>
{{out}}
<pre >
Line 3,494 ⟶ 3,760:
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
{{trans|Ruby}}
<syntaxhighlight lang="text">compress[uncompressed_] :=
Module[{dictsize, dictionary, w, result, wc},
dictsize = 256;
Line 3,532 ⟶ 3,798:
(*How to use:*)
compress["TOBEORNOTTOBEORTOBEORNOT"]
decompress[%]</langsyntaxhighlight>
{{Out}}
<pre>{"T", "O", "B", "E", "O", "R", "N", "O", "T", 256, 258, 260, 265, 259, 261, 263}
 
"TOBEORNOTTOBEORTOBEORNOT"</pre>
 
(* stm, 6 June 2022: I did not edit the above code, but I believe that there is a small error. The Range@dictsize should be replaced by Range[0,dictsize-1] for LZW standard; Mathematica runs from 1 to 256 instead of 0 to 255. The code works as is in String format in Mathematica because Mathematica distinguishes between Strings and numbers. However, this example fails when the code is adapted to byte type input and output, as used in images. Adjusting Range[...] fixes the problem.*)
 
=={{header|Nim}}==
<syntaxhighlight lang="text">import tables
<lang>
import tables
 
proc compress*(uncompressed: string): seq[int] =
## build the dictionary
var dictionary = initTable[string, int]()
for i in 0..255:
dictionary.add($char(i), i)
 
# Build the dictionary.
var w: string = newString(0)
var compresseddictionary: = newSeqTable[string, int]()
for i in 0..255: dictionary[$chr(i)] = i
 
var w = ""
for c in uncompressed:
var wc = w & c
if(dictionary.hasKey( wc)) in dictionary:
w = wc
else:
# writesWrites "w" to output.
compressedresult.add( dictionary[w])
# "wc" is a new sequence;: add it to the dictionary.
dictionary.add([wc,] = dictionary.len)
w = $c
 
# writeWrite remaining output if necessary.
if w.len > 0: result.add dictionary[w]
if(w != nil):
compressed.add(dictionary[w])
 
result = compressed
 
proc decompress*(compressed: var seq[int]): string =
# build the dictionary
var dictionary = initTable[int, string]()
for i in 0..255:
dictionary.add(i, $char(i))
 
var# w:Build string =the dictionary[compressed[0]].
var dictionary: Table[int, string]
for i in 0..255: dictionary[i] = $chr(i)
 
var w = dictionary[compressed[0]]
compressed.delete(0)
 
var decompressedresult = w
 
for k in compressed:
var entry: string = newString(0)
if k in dictionary:
if(dictionary.hasKey(k)):
entry = dictionary[k]
elif( k == dictionary.len):
entry = w & w[0]
else:
raise newException(ValueError, "Bad compressed k: " & $k)
result.add entry
 
# New sequence: add it to the dictionary.
decompressed &= entry
dictionary[dictionary.len] = w & entry[0]
 
# new sequence; add it to the dictionary
dictionary.add(dictionary.len, w & entry[0])
 
w = entry
 
result = decompressed
 
when isMainModule:
Line 3,602 ⟶ 3,858:
echo compressed
var decompressed = decompress(compressed)
echo decompressed</syntaxhighlight>
 
</lang>
{{Outout}}
<pre>@[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
<pre>
TOBEORNOTTOBEORTOBEORNOT</pre>
@[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
TOBEORNOTTOBEORTOBEORNOT
</pre>
 
=={{header|Objeck}}==
{{trans|Java}}
<langsyntaxhighlight lang="objeck">use Collection;
 
class LZW {
Line 3,715 ⟶ 3,969:
"]"->PrintLine();
}
}</langsyntaxhighlight>
 
<pre>[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
Line 3,726 ⟶ 3,980:
The class for the LZW compression algorithm:
 
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
#import <stdio.h>
 
Line 3,811 ⟶ 4,065:
}
 
@end</langsyntaxhighlight>
 
Usage example:
 
<langsyntaxhighlight lang="objc">NSString *text = @"TOBEORNOTTOBEORTOBEORNOT";
 
int main()
Line 3,835 ⟶ 4,089:
}
return EXIT_SUCCESS;
}</langsyntaxhighlight>
 
{{out}} (reformatted by hand):
Line 3,845 ⟶ 4,099:
=={{header|OCaml}}==
 
<langsyntaxhighlight lang="ocaml">#directory "+extlib" (* or maybe "+site-lib/extlib/" *)
#load "extLib.cma"
open ExtString
Line 3,924 ⟶ 4,178:
in
(List.rev result)
;;</langsyntaxhighlight>
 
here is the interface:
<langsyntaxhighlight lang="ocaml">val compress : uncompressed:string -> int list
val decompress : compressed:int list -> string list</langsyntaxhighlight>
 
How to use:<br />
Line 3,934 ⟶ 4,188:
So to know how many bits are required, you need to know how many bits are required for the greatest symbol in the list.
 
<langsyntaxhighlight lang="ocaml">let greatest = List.fold_left max 0 ;;
 
(** number of bits needed to encode the integer m *)
Line 3,972 ⟶ 4,226:
List.iter (Buffer.add_string buf) result;
(Buffer.contents buf)
;;</langsyntaxhighlight>
 
=={{header|Ol}}==
This version use lazy streams which is pair (symbol . function-to-get-next-symbol).
<langsyntaxhighlight lang="scheme">
(define (compress str)
(let loop ((dc (fold (lambda (f x) ; dictionary (simplest, not optimized), with reversed codes
Line 4,002 ⟶ 4,256:
 
(print (compress "TOBEORNOTTOBEORTOBEORNOT")) ; => (84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263)
</syntaxhighlight>
</lang>
 
And decoder (runes->string used to unify functions - both used string iterators):
<langsyntaxhighlight lang="scheme">
(define (decompress str)
(let loop ((dc (fold (lambda (f x) ; dictionary (simplest, not optimized), with reversed codes
Line 4,033 ⟶ 4,287:
(decompress (runes->string '(84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263)))))
; => TOBEORNOTTOBEORTOBEEORNOT
</syntaxhighlight>
</lang>
 
=={{header|Perl}}==
 
In this version the hashes contain mixed typed data:
<langsyntaxhighlight lang="perl"># Compress a string to a list of output symbols.
sub compress {
my $uncompressed = shift;
Line 4,102 ⟶ 4,356:
print "@compressed\n";
my $decompressed = decompress(@compressed);
print "$decompressed\n";</langsyntaxhighlight>
 
{{out}}
Line 4,112 ⟶ 4,366:
=={{header|Phix}}==
{{trans|Lua}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function compress(string uncompressed)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
integer dict = new_dict()
<span style="color: #008080;">function</span> <span style="color: #000000;">compress</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">uncompressed</span><span style="color: #0000FF;">)</span>
sequence result = {}
<span style="color: #004080;">integer</span> <span style="color: #000000;">dict</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
integer dictSize = 255, c
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
string word = ""
<span style="color: #004080;">integer</span> <span style="color: #000000;">dictSize</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">255</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span>
for i=0 to 255 do
<span style="color: #004080;">string</span> <span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
setd(""&i,i,dict)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">255</span> <span style="color: #008080;">do</span>
end for
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">&</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
for i=1 to length(uncompressed) do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
c = uncompressed[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">uncompressed</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if getd_index(word&c,dict) then
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">uncompressed</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
word &= c
<span style="color: #008080;">if</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">&</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">word</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">c</span>
result &= getd(word,dict)
<span dictSize +style="color: 1#008080;">else</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
setd(word&c,dictSize,dict)
<span style="color: #000000;">dictSize</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
word = ""&c
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">&</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dictSize</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">&</span><span style="color: #000000;">c</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if word!="" then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
result &= getd(word,dict)
<span style="color: #008080;">if</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">""</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">result</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
destroy_dict(dict)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return result
<span style="color: #7060A8;">destroy_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function decompress(sequence compressed)
integer dict = new_dict()
<span style="color: #008080;">function</span> <span style="color: #000000;">decompress</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">compressed</span><span style="color: #0000FF;">)</span>
integer dictSize = 255, k, ki
<span style="color: #004080;">integer</span> <span style="color: #000000;">dict</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
string dent = "", result = "", word = ""
<span style="color: #004080;">integer</span> <span style="color: #000000;">dictSize</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">255</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ki</span>
for i=0 to 255 do
<span style="color: #004080;">string</span> <span style="color: #000000;">dent</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
setd(i,""&i,dict)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">255</span> <span style="color: #008080;">do</span>
end for
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">&</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
for i=1 to length(compressed) do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
k = compressed[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">compressed</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
ki = getd_index(k,dict)
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">compressed</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
if ki then
<span style="color: #000000;">ki</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
dent = getd_by_index(ki,dict)
<span style="color: #008080;">if</span> <span style="color: #000000;">ki</span> <span style="color: #008080;">then</span>
elsif k=dictSize then
<span style="color: #000000;">dent</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_by_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ki</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
dent = word&word[1]
<span style="color: #008080;">elsif</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">dictSize</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">dent</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">&</span><span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
return {NULL,i}
<span style="color: #008080;">else</span>
end if
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">}</span>
result &= dent
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
setd(dictSize,word&dent[1],dict)
<span style="color: #000000;">result</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">dent</span>
dictSize += 1
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dictSize</span><span style="color: #0000FF;">,</span><span style="color: #000000;">word</span><span style="color: #0000FF;">&</span><span style="color: #000000;">dent</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
word = dent
<span style="color: #000000;">dictSize</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end for
<span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dent</span>
destroy_dict(dict)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return result
<span style="color: #7060A8;">destroy_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant example = "TOBEORNOTTOBEORTOBEORNOT"
sequence com = compress(example)
<span style="color: #008080;">constant</span> <span style="color: #000000;">example</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"TOBEORNOTTOBEORTOBEORNOT"</span>
--?com
<span style="color: #004080;">sequence</span> <span style="color: #000000;">com</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">compress</span><span style="color: #0000FF;">(</span><span style="color: #000000;">example</span><span style="color: #0000FF;">)</span>
pp(com)
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">com</span><span style="color: #0000FF;">,{</span><span style="color: #004600;">pp_IntCh</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">pp_Maxlen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">})</span>
?decompress(com)
<span style="color: #0000FF;">?</span><span style="color: #000000;">decompress</span><span style="color: #0000FF;">(</span><span style="color: #000000;">com</span><span style="color: #0000FF;">)</span>
</lang>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 4,178 ⟶ 4,433:
=={{header|PHP}}==
{{trans|JavaScript}}
<langsyntaxhighlight PHPlang="php">class LZW
{
function compress($unc) {
Line 4,219 ⟶ 4,474:
for ($i = 1; $i < count($com);$i++) {
$k = $com[$i];
if (isset($dictionary[$k])) {
$entry = $dictionary[$k];
} else {
Line 4,242 ⟶ 4,497:
$dec = $lzw->decompress($com);
echo $com . "<br>" . $dec;
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 4,248 ⟶ 4,503:
TOBEORNOTTOBEORTOBEORNOT
</pre>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">go =>
S = "TOBEORNOTTOBEORTOBEORNOT",
println(s=S),
println(len=S.length),
 
Compressed = compress(S),
println(compressed=Compressed),
println(len=Compressed.length),
Uncompressed = uncompress(Compressed),
println(uncompressed=Uncompressed),
printf("compressed to %3.3f%%\n", 100*(Compressed.length / S.length)),
 
if S = Uncompressed then
println("Same!")
else
println("Error: S != Uncompressed!"),
printf("S.length: %d Uncompressed.length: %d\n", S.length, Uncompressed.length),
edit(S,Uncompressed,Distance,Diffs),
println(distance=Distance),
println(diffs=Diffs)
end,
nl.
 
compress(Uncompressed) = Compressed =>
DictSize = 256,
Dict = new_map([C=C : I in 1..DictSize-1, C=chr(I).to_string()]),
W = "",
Result = [],
foreach(C in Uncompressed)
C := C.to_string(),
WC = W ++ C,
if Dict.has_key(WC) then
W := WC
else
Result := Result ++ [Dict.get(W)],
Dict.put(WC, DictSize),
DictSize := DictSize + 1,
W := C
end
end,
if W.length > 0 then
Result := Result ++ [Dict.get(W)]
end,
Compressed = Result.
 
uncompress(Compressed) = Uncompressed =>
DictSize = 256,
Dict = new_map([ C=C : I in 1..DictSize-1, C=chr(I).to_string()]),
W = Compressed.first(),
Compressed := Compressed.tail(),
Result = W,
 
Entry = "",
foreach(K in Compressed)
if Dict.has_key(K) then
Entry := Dict.get(K)
elseif K == DictSize then
Entry := W ++ W[1].to_string()
else
printf("Bad compressed K: %w\n", K)
end,
Result := Result ++ Entry,
Dict.put(DictSize,(W ++ Entry[1].to_string())),
DictSize := DictSize + 1,
W := Entry
end,
Uncompressed = Result.flatten().
 
%
% Computing the minimal editing distance of two given lists
%
table(+,+,min,-)
edit([],[],D,Diffs) => D=0, Diffs=[].
edit([X|Xs],[X|Ys],D,Diffs) => % copy
edit(Xs,Ys,D,Diffs).
edit(Xs,[Y|Ys],D,Diffs) ?=> % insert
edit(Xs,Ys,D1,Diffs1),
D=D1+1,
Diffs = [insert=Y,xPos=Xs.length,yPos=Ys.length|Diffs1].
edit([X|Xs],Ys,D,Diffs) => % delete
edit(Xs,Ys,D1,Diffs1),
D=D1+1,
Diffs = [[delete=X,xPos=Xs.length,yPos=Ys.length]|Diffs1].</syntaxhighlight>
 
{{out}}
<pre>s = TOBEORNOTTOBEORTOBEORNOT
len = 24
compressed = [T,O,B,E,O,R,N,O,T,256,258,260,265,259,261,263]
len = 16
uncompressed = TOBEORNOTTOBEORTOBEORNOT
compressed to 66.667%
Same!</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de lzwCompress (Lst)
(let (Codes 255 Dict)
(balance 'Dict
Line 4,280 ⟶ 4,631:
(when W
(idx 'Dict (cons (inc 'Codes) (cons (last WC) W)) T) )
(setq W WC) ) ) ) ) ) )</langsyntaxhighlight>
Test:
<pre>: (lzwCompress (chop "TOBEORNOTTOBEORTOBEORNOT"))
Line 4,291 ⟶ 4,642:
{{trans|REXX}}
The interesting point is the implementation of REXX's associative array (compound variable).
<langsyntaxhighlight lang="pli">*process source xref attributes or(!);
lzwt: Proc Options(main);
 
Line 4,440 ⟶ 4,791:
Return;
 
End;</langsyntaxhighlight>
{{out}}
<pre>str=TOBEORNOTTOBEORTOBEORNOT
Line 4,452 ⟶ 4,803:
This is because PureBasic uses these to terminate strings.
Only slight modifications are necessary to handle Null values that would be present for a more generic routine that could be used with a buffer containing any data type.
<langsyntaxhighlight PureBasiclang="purebasic">Procedure compress(uncompressed.s, List result.u())
;Compress a string to a list of output symbols
Line 4,548 ⟶ 4,899:
Input()
CloseConsole()
EndIf</langsyntaxhighlight>
Sample output:
<pre>Type something: TOBEORNOTTOBEORTOBEORNOT
Line 4,557 ⟶ 4,908:
{{works with|Python|3.x}}
In this version the dicts contain mixed typed data:
<langsyntaxhighlight lang="python">def compress(uncompressed):
"""Compress a string to a list of output symbols."""
 
Line 4,619 ⟶ 4,970:
print (compressed)
decompressed = decompress(compressed)
print (decompressed)</langsyntaxhighlight>
 
Output:
Line 4,628 ⟶ 4,979:
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">
#lang racket
; utilities
Line 4,686 ⟶ 5,037:
(def decompressed (decompress compressed))
(displayln decompressed)
</syntaxhighlight>
</lang>
 
Output:
Line 4,698 ⟶ 5,049:
(formerly Perl 6) I just came across [https://stackoverflow.com/questions/30531078/ this SO question] by chance hence the update. Notably the ancestor Perl entry simply works without any further tweak.
{{trans|Perl}}
<syntaxhighlight lang="raku" perl6line># 20200421 Updated Raku programming solution ; add unicode support
 
sub compress(Str $uncompressed --> Seq) {
Line 4,743 ⟶ 5,094:
 
@compressed = compress('こんにちは𝒳𝒴𝒵こんにちは𝒳𝒴𝒵こんにちは𝒳𝒴𝒵');
say decompress(@compressed);</langsyntaxhighlight>
{{out}}
<pre>
Line 4,754 ⟶ 5,105:
===version 1===
{{trans|Java}}
<langsyntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* 20.07.2014 Walter Pachl translated from Java
* 21.07.2014 WP allow for blanks in the string
Line 4,829 ⟶ 5,180:
w=entry
End
Return res</langsyntaxhighlight>
'''Output:'''
<pre>str=TOBEORNOTTOBEORTOBEORNOT
Line 4,847 ⟶ 5,198:
 
This REXX version can execute on &nbsp; '''ASCII''' &nbsp; or &nbsp; '''EBCDIC''' &nbsp; systems.
<langsyntaxhighlight lang="rexx">/*REXX program compresses text using the LZW (Lempel─Ziv─Welch), and reconstitutes it.*/
$$$= '"There is nothing permanent except change." ─── Heraclitus [540 ── 475 BCE]'
parse arg x; if x='' then , /*get an optional argument from the CL.*/
parse arg text; if text='' then text= $$$ /*get an optional argument from the CL.*/
x= '"There is nothing permanent except change." ─── Heraclitus [540 ── 475 BCE]'
say 'original text=' text x /* [↑] Not specified? Then use default*/
cypher= LZWc(xtext) /*compress text using the LZW algorithm*/
say 'reconstituted=' LZWd(cypher) /*display the reconstituted string. */
say; say ' LZW integers=' cypher /* " " LZW integers used. */
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
LZWcLZWi: procedure; parse arg yi,,w $ @.; #=256; do j=0 for #; _=d2c(j); 256if i then @.j=_; else @._=j; end; /*LZW compress algorithm.*/return
do j=0 for #; _= d2c(j); @._= j; end /*j*/
do k=1 for length(y)+1; z= w || substr(y, k, 1)
if @.z=='' then do; $= $ @.w; @.z= #; #= # + 1; w= substr(y, k, 1); end
else w= z /*#: the dictionary size.*/
end /*k*/; return substr($, 2) /*elide a leading blank. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
LZWdLZWc: procedure; parse arg x y,,@.$; call LZWi 0; #w= 256 /*LZW decompress algorithm compress.*/
do k=1 for length(y)+1; do jz=0 w for|| #;substr(y, k, @.j= d2c(j1); end /*j*/
$= if @.x; wz=='' $ then do; $= $ @.w; @.z= #; #= # + 1; w= substr(y, k, 1); /*#: the dictionary size.*/end
else w= z do k=1 for words(y); z= word(y, k) /*#: the dictionary size.*/
end /*k*/; if @.z\=='' | @.k==" " then ?= @ return substr($, 2) /*elide a leading blank.z */
/*──────────────────────────────────────────────────────────────────────────────────────*/
else if z==# then ?= w || left(w, 1)
LZWd: procedure; parse arg x y; call LZWi 1; $= @.x; $w= $ || /*LZW ?decompress.*/
do @.#k=1 w ||for leftwords(?, 1y); w= ?; #z= #word(y, + 1 /*bump dict. size.*/k)
if @.z\=='' | end /*@.k*/; ==" " then return?= $</lang>@.z
else if z==# then ?= w || left(w, 1)
$= $ || ?
@.#= w || left(?, 1); w= ?; #= # + 1 /*bump dict. size*/
end /*k*/; return $</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
original text= "There is nothing permanent except change." ─── Heraclitus [540 ── 475 BCE]
reconstituted= "There is nothing permanent except change." ─── Heraclitus [540 ── 475 BCE]
 
LZW integers= 34 84 104 101 114 101 32 105 115 32 110 111 116 104 105 110 103 32 112 259 109 97 110 101 110 116 32 101 120 99 101 112 281 99 104 277 103 101 46 34 32 296 196 298 296 32 72 259 97 99 108 105 116 117 264 32 91 53 52 48 32 299 52 55 53 32 66 67 69 93
</pre>
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : LZW compression
 
Line 4,959 ⟶ 5,310:
svect = left(svect, len(svect) - 1)
see svect + nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 4,969 ⟶ 5,320:
 
In this version the hashes contain mixed typed data:
<langsyntaxhighlight lang="ruby"># Compress a string to a list of output symbols.
def compress(uncompressed)
# Build the dictionary.
Line 5,025 ⟶ 5,376:
p compressed
decompressed = decompress(compressed)
puts decompressed</langsyntaxhighlight>
 
Output:
Line 5,036 ⟶ 5,387:
{{trans|C Sharp}}
Handles arbitrary byte sequences.
<langsyntaxhighlight lang="rust">use std::collections::HashMap;
 
fn compress(data: &[u8]) -> Vec<u32> {
Line 5,112 ⟶ 5,463:
let decompressed = String::from_utf8(decompressed).unwrap();
println!("{}", decompressed);
}</langsyntaxhighlight>
 
Output:
Line 5,121 ⟶ 5,472:
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">
def compress(tc:String) = {
//initial dictionary
Line 5,167 ⟶ 5,518:
val result = decompress(compressed)
println(result)
</syntaxhighlight>
</lang>
 
=={{header|Scheme}}==
<langsyntaxhighlight lang="scheme">; Get the list reference number for a member or #f if not found
(define (member-string-ref m l)
(define r #f)
Line 5,254 ⟶ 5,605:
(display compressed) (newline)
(define decompressed (lzw-decompress compressed))
(display decompressed) (newline)</langsyntaxhighlight>
Output:<pre>(84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263)
TOBEORNOTTOBEORTOBEORNOT</pre>
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
const func string: lzwCompress (in string: uncompressed) is func
Line 5,333 ⟶ 5,684:
uncompressed := lzwDecompress(compressed);
writeln(uncompressed);
end func;</langsyntaxhighlight>
 
Output:
Line 5,345 ⟶ 5,696:
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby"># Compress a string to a list of output symbols.
func compress(String uncompressed) -> Array {
Line 5,416 ⟶ 5,767:
say compressed.join(' ')
var decompressed = decompress(compressed)
say decompressed</langsyntaxhighlight>
{{out}}
<pre>T O B E O R N O T 256 258 260 265 259 261 263
Line 5,423 ⟶ 5,774:
=={{header|Swift}}==
{{trans|JavaScript}}
<langsyntaxhighlight lang="swift">class LZW {
class func compress(_ uncompressed:String) -> [Int] {
var dict = [String : Int]()
Line 5,441 ⟶ 5,792:
} else {
result.append(dict[w]!)
dict[wc] = dictSize + 1
dictSize += 1
w = String(c)
}
Line 5,473 ⟶ 5,825:
 
result += entry
dict[dictSize+1] = w + String(entry[entry.startIndex])
dictSize += 1
w = entry
}
Line 5,485 ⟶ 5,838:
if let decomp = LZW.decompress(comp) {
print(decomp)
}</langsyntaxhighlight>
{{out}}
<pre>
[84, 79, 66, 69, 79, 82, 78, 79, 84, 257256, 257258, 257260, 257265, 257259, 257261, 257263]
TOBEORNOTTOBEORTOBEORNOT
TOBEORNOTOTTOOTTTOOOTTTTOOOOTTTT
</pre>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">namespace eval LZW {
variable char2int
variable chars
Line 5,552 ⟶ 5,905:
 
# or
if {$s eq [LZW::decode [LZW::encode $s]]} then {puts success} else {puts fail} ;# ==> success</langsyntaxhighlight>
 
=={{header|VBScript}}==
<syntaxhighlight lang="vb">
Option Explicit
Const numchars=127 'plain ASCII
 
Function LZWCompress(si)
Dim oDict, intMaxCode, i,z,ii,ss,strCurrent,strNext,j
Set oDict = CreateObject("Scripting.Dictionary")
ReDim a(Len(si))
intMaxCode = numchars
For i = 0 To numchars
oDict.Add Chr(i), i
Next
'strCurrent = ofread.ReadText(1)
strCurrent = Left(si,1)
j=0
For ii=2 To Len(si)
strNext = Mid(si,ii,1)
ss=strCurrent & strNext
If oDict.Exists(ss) Then
strCurrent = ss
Else
a(j)=oDict.Item(strCurrent) :j=j+1
intMaxCode = intMaxCode + 1
oDict.Add ss, intMaxCode
strCurrent = strNext
End If
Next
a(j)=oDict.Item(strCurrent)
ReDim preserve a(j)
LZWCompress=a
Set oDict = Nothing
End Function
 
Function lzwUncompress(sc)
Dim intNext, intCurrent, intMaxCode, i,ss,istr,s,j
s=""
reDim dict(1000)
intMaxCode = numchars
For i = 0 To numchars : dict(i)= Chr(i) : Next
intCurrent=sc(0)
For j=1 To UBound(sc)
ss=dict(intCurrent)
s= s & ss
intMaxCode = intMaxCode + 1
intnext=sc(j)
If intNext<intMaxCode Then
dict(intMaxCode)=ss & Left(dict(intNext), 1)
Else
dict(intMaxCode)=ss & Left(ss, 1)
End If
intCurrent = intNext
Next
s= s & dict(intCurrent)
lzwUncompress=s
End function
 
Sub printvec(a)
Dim s,i,x
s="("
For i=0 To UBound (a)
s=s & x & a(i)
x=", "
Next
WScript.echo s &")"
End sub
 
Dim a,b
b="TOBEORNOTTOBEORTOBEORNOT"
WScript.Echo b
a=LZWCompress (b)
printvec(a)
WScript.echo lzwUncompress (a )
wscript.quit 1
</syntaxhighlight>
{{out}}
<small>
<pre>
 
TOBEORNOTTOBEORTOBEORNOT
(84, 79, 66, 69, 79, 82, 78, 79, 84, 128, 130, 132, 137, 131, 133, 135)
TOBEORNOTTOBEORTOBEORNOT
</pre>
</small>
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="wren">class LZW {
/* Compress a string to a list of output symbols. */
static compress(uncompressed) {
// Build the dictionary.
var dictSize = 256
var dictionary = {}
for (i in 0...dictSize) dictionary[String.fromByte(i)] = i
var w = ""
var result = []
for (c in uncompressed.bytes) {
var cs = String.fromByte(c)
var wc = w + cs
if (dictionary.containsKey(wc)) {
w = wc
} else {
result.add(dictionary[w])
// Add wc to the dictionary.
dictionary[wc] = dictSize
dictSize = dictSize + 1
w = cs
}
}
 
// Output the code for w
if (w != "") result.add(dictionary[w])
return result
}
 
/* Decompress a list of output symbols to a string. */
static decompress(compressed) {
// Build the dictionary.
var dictSize = 256
var dictionary = {}
for (i in 0...dictSize) dictionary[i] = String.fromByte(i)
var w = String.fromByte(compressed[0])
var result = w
for (k in compressed.skip(1)) {
var entry
if (dictionary.containsKey(k)) {
entry = dictionary[k]
} else if (k == dictSize) {
entry = w + String.fromByte(w.bytes[0])
} else {
Fiber.abort("Bad compressed k: %(k)")
}
result = result + entry
 
// Add w + entry[0] to the dictionary.
dictionary[dictSize] = w + String.fromByte(entry.bytes[0])
dictSize = dictSize + 1
w = entry
}
return result
}
}
 
var compressed = LZW.compress("TOBEORNOTTOBEORTOBEORNOT")
System.print(compressed)
var decompressed = LZW.decompress(compressed)
System.print(decompressed)</syntaxhighlight>
 
{{out}}
<pre>
[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
TOBEORNOTTOBEORTOBEORNOT
</pre>
 
=={{header|Xojo}}==
{{trans|PHP}}
<syntaxhighlight lang="vb">
<lang vb>
Function compress(str as String) As String
Dim i as integer
Line 5,663 ⟶ 6,171:
End Function
 
</syntaxhighlight>
</lang>
 
Test:
Line 5,680 ⟶ 6,188:
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn lzwCompress(uncompressed){ // text-->list of 12 bit ints
dictionary:=(256).pump(Dictionary(),fcn(n){ return(n.toChar(),n) });
w,compressed:="",List();
Line 5,707 ⟶ 6,215:
}
decommpressed.text
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">compressed:=lzwCompress("TOBEORNOTTOBEORTOBEORNOT");
compressed.toString(*).println();
 
lzwUncompress(compressed).println();</langsyntaxhighlight>
{{out}}
<pre>
413

edits