Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,3 @@
---
from: http://rosettacode.org/wiki/LZW_compression
note: Compression

View file

@ -0,0 +1,5 @@
The Lempel-Ziv-Welch (LZW) algorithm provides loss-less data compression.
You can read a complete description of it in the   [[wp:Lempel-Ziv-Welch|Wikipedia article]]   on the subject.   It was patented, but it entered the public domain in 2004.
<br><br>

View file

@ -0,0 +1,44 @@
F compress(uncompressed)
V dict_size = 256
V dictionary = Dict((0 .< dict_size).map(i -> (String(Char(code' i)), i)))
V w =
[Int] result
L(c) uncompressed
V wc = wc
I wc C dictionary
w = wc
E
result.append(dictionary[w])
dictionary[wc] = dict_size
dict_size++
w = c
I !w.empty
result.append(dictionary[w])
R result
F decompress([Int] &compressed)
V dict_size = 256
V dictionary = Dict((0 .< dict_size).map(i -> (i, String(Char(code' i)))))
V result =
V w = String(Char(code' compressed.pop(0)))
result = w
L(k) compressed
V entry =
I k C dictionary
entry = dictionary[k]
E I k == dict_size
entry = ww[0]
E
exit(Bad compressed k: k)
result = entry
dictionary[dict_size] = wentry[0]
dict_size++
w = entry
R result
V compressed = compress(TOBEORNOTTOBEORTOBEORNOT)
print(compressed)
print(decompress(&compressed))

View file

@ -0,0 +1,9 @@
==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

View file

@ -0,0 +1,73 @@
# 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)
}

View file

@ -0,0 +1,11 @@
package LZW is
MAX_CODE : constant := 4095;
type Codes is new Natural range 0 .. MAX_CODE;
type Compressed_Data is array (Positive range <>) of Codes;
function Compress (Cleartext : in String) return Compressed_Data;
function Decompress (Data : in Compressed_Data) return String;
end LZW;

View file

@ -0,0 +1,116 @@
with Ada.Containers.Ordered_Maps;
with Ada.Strings.Unbounded;
package body LZW is
package UStrings renames Ada.Strings.Unbounded;
use type UStrings.Unbounded_String;
--------------
-- Compress --
--------------
function Compress (Cleartext : in String) return Compressed_Data is
-- translate String to Code-ID
package String_To_Code is new Ada.Containers.Ordered_Maps (
Key_Type => UStrings.Unbounded_String,
Element_Type => Codes);
Dictionary : String_To_Code.Map;
-- Next unused Code-ID
Next_Entry : Codes := 256;
-- maximum same length as input, compression ratio always >=1.0
Result : Compressed_Data (1 .. Cleartext'Length);
-- position for next Code-ID
Result_Index : Natural := 1;
-- current and next input string
Current_Word : UStrings.Unbounded_String :=
UStrings.Null_Unbounded_String;
Next_Word : UStrings.Unbounded_String :=
UStrings.Null_Unbounded_String;
begin
-- initialize Dictionary
for C in Character loop
String_To_Code.Insert
(Dictionary,
UStrings.Null_Unbounded_String & C,
Character'Pos (C));
end loop;
for Index in Cleartext'Range loop
-- add character to current word
Next_Word := Current_Word & Cleartext (Index);
if String_To_Code.Contains (Dictionary, Next_Word) then
-- already in dictionary, continue with next character
Current_Word := Next_Word;
else
-- insert code for current word to result
Result (Result_Index) :=
String_To_Code.Element (Dictionary, Current_Word);
Result_Index := Result_Index + 1;
-- add new Code to Dictionary
String_To_Code.Insert (Dictionary, Next_Word, Next_Entry);
Next_Entry := Next_Entry + 1;
-- reset current word to one character
Current_Word := UStrings.Null_Unbounded_String &
Cleartext (Index);
end if;
end loop;
-- Last word was not entered
Result (Result_Index) :=
String_To_Code.Element (Dictionary, Current_Word);
-- return correct array size
return Result (1 .. Result_Index);
end Compress;
----------------
-- Decompress --
----------------
function Decompress (Data : in Compressed_Data) return String is
-- translate Code-ID to String
type Code_To_String is array (Codes) of UStrings.Unbounded_String;
Dictionary : Code_To_String;
-- next unused Code-ID
Next_Entry : Codes := 256;
-- initialize resulting string as empty string
Result : UStrings.Unbounded_String := UStrings.Null_Unbounded_String;
Next_Code : Codes;
-- first code has to be in dictionary
Last_Code : Codes := Data (1);
-- suffix appended to last string for new dictionary entry
Suffix : Character;
begin
-- initialize Dictionary
for C in Character loop
Dictionary (Codes (Character'Pos (C))) :=
UStrings.Null_Unbounded_String & C;
end loop;
-- output first Code-ID
UStrings.Append (Result, Dictionary (Last_Code));
for Index in 2 .. Data'Last loop
Next_Code := Data (Index);
if Next_Code <= Next_Entry then
-- next Code-ID already in dictionary -> append first char
Suffix := UStrings.Element (Dictionary (Next_Code), 1);
else
-- next Code-ID not in dictionary -> use char from last ID
Suffix := UStrings.Element (Dictionary (Last_Code), 1);
end if;
-- expand the dictionary
Dictionary (Next_Entry) := Dictionary (Last_Code) & Suffix;
Next_Entry := Next_Entry + 1;
-- output the current Code-ID to result
UStrings.Append (Result, Dictionary (Next_Code));
Last_Code := Next_Code;
end loop;
-- return String
return UStrings.To_String (Result);
end Decompress;
end LZW;

View file

@ -0,0 +1,21 @@
with LZW;
with Ada.Text_IO;
procedure Test is
package Text_IO renames Ada.Text_IO;
package Code_IO is new Ada.Text_IO.Integer_IO (LZW.Codes);
Test_Data : constant LZW.Compressed_Data :=
LZW.Compress ("TOBEORNOTTOBEORTOBEORNOT");
begin
for Index in Test_Data'Range loop
Code_IO.Put (Test_Data (Index), 0);
Text_IO.Put (" ");
end loop;
Text_IO.New_Line;
declare
Cleartext : constant String := LZW.Decompress (Test_Data);
begin
Text_IO.Put_Line (Cleartext);
end;
end Test;

View file

@ -0,0 +1,52 @@
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

View file

@ -0,0 +1,48 @@
plaintext$ = "TOBEORNOTTOBEORTOBEORNOT"
encodeLZW$ = FNencodeLZW(plaintext$)
FOR i% = 1 TO LEN(encodeLZW$) STEP 2
PRINT ; ASCMID$(encodeLZW$,i%) + 256*ASCMID$(encodeLZW$,i%+1) " " ;
NEXT
PRINT ' FNdecodeLZW(encodeLZW$)
END
DEF FNencodeLZW(i$)
LOCAL c%, d%, i%, l%, o$, w$, dict$()
DIM dict$(4095)
FOR i% = 0 TO 255 : dict$(i%) = CHR$(i%) : NEXT
l% = i%
i% = 1
w$ = LEFT$(i$,1)
REPEAT
d% = 0
REPEAT
c% = d%
IF i% > LEN(i$) EXIT REPEAT
FOR d% = 1 TO l%-1
IF w$ = dict$(d%) EXIT FOR
NEXT d%
IF d% < l% i% += 1 : w$ += MID$(i$, i%, 1)
UNTIL d% >= l%
dict$(l%) = w$ : l% += 1 : w$ = RIGHT$(w$)
o$ += CHR$(c% MOD 256) + CHR$(c% DIV 256)
UNTIL i% >= LEN(i$)
= o$
DEF FNdecodeLZW(i$)
LOCAL c%, i%, l%, o$, t$, w$, dict$()
DIM dict$(4095)
FOR i% = 0 TO 255 : dict$(i%) = CHR$(i%) : NEXT
l% = i%
c% = ASC(i$) + 256*ASCMID$(i$,2)
w$ = dict$(c%)
o$ = w$
IF LEN(i$) < 4 THEN = o$
FOR i% = 3 TO LEN(i$) STEP 2
c% = ASCMID$(i$,i%) + 256*ASCMID$(i$,i%+1)
IF c% < l% t$ = dict$(c%) ELSE t$ = w$ + LEFT$(w$,1)
o$ += t$
dict$(l%) = w$ + LEFT$(t$,1)
l% += 1
w$ = t$
NEXT
= o$

View file

@ -0,0 +1,76 @@
CONST lzw_data$ = "TOBEORNOTTOBEORTOBEORNOT"
PRINT "LZWData: ", lzw_data$
encoded$ = Encode_LZW$(lzw_data$)
PRINT "Encoded: ", encoded$
PRINT "Decoded: ", Decode_LZW$(encoded$)
'----------------------------------------------------------
FUNCTION Encode_LZW$(sample$)
LOCAL dict ASSOC int
LOCAL ch$, buf$, result$
LOCAL nr, x
FOR nr = 0 TO 255
dict(CHR$(nr)) = nr
NEXT
FOR x = 1 TO LEN(sample$)
ch$ = MID$(sample$, x, 1)
IF dict(buf$ & ch$) THEN
buf$ = buf$ & ch$
ELSE
result$ = APPEND$(result$, 0, STR$(dict(buf$)))
dict(buf$ & ch$) = nr
INCR nr
buf$ = ch$
END IF
NEXT
result$ = APPEND$(result$, 0, STR$(dict(buf$)))
RETURN result$
END FUNCTION
'----------------------------------------------------------
FUNCTION Decode_LZW$(sample$)
LOCAL list$ ASSOC STRING
LOCAL old$, ch$, x$, out$, result$
LOCAL nr
FOR nr = 0 TO 255
list$(STR$(nr)) = CHR$(nr)
NEXT
old$ = TOKEN$(sample$, 1)
ch$ = list$(old$)
result$ = ch$
FOR x$ IN LAST$(sample$, 1)
IF NOT(LEN(list$(x$))) THEN
out$ = list$(old$)
out$ = out$ & ch$
ELSE
out$ = list$(x$)
END IF
result$ = result$ & out$
ch$ = LEFT$(out$, 1)
list$(STR$(nr)) = list$(old$) & ch$
INCR nr
old$ = x$
NEXT
RETURN result$
END FUNCTION

View file

@ -0,0 +1,81 @@
#include <string>
#include <map>
// Compress a string to a list of output symbols.
// The result will be written to the output iterator
// starting at "result"; the final iterator is returned.
template <typename Iterator>
Iterator compress(const std::string &uncompressed, Iterator result) {
// Build the dictionary.
int dictSize = 256;
std::map<std::string,int> dictionary;
for (int i = 0; i < 256; i++)
dictionary[std::string(1, i)] = i;
std::string w;
for (std::string::const_iterator it = uncompressed.begin();
it != uncompressed.end(); ++it) {
char c = *it;
std::string wc = w + c;
if (dictionary.count(wc))
w = wc;
else {
*result++ = dictionary[w];
// Add wc to the dictionary.
dictionary[wc] = dictSize++;
w = std::string(1, c);
}
}
// Output the code for w.
if (!w.empty())
*result++ = dictionary[w];
return result;
}
// Decompress a list of output ks to a string.
// "begin" and "end" must form a valid range of ints
template <typename Iterator>
std::string decompress(Iterator begin, Iterator end) {
// Build the dictionary.
int dictSize = 256;
std::map<int,std::string> dictionary;
for (int i = 0; i < 256; i++)
dictionary[i] = std::string(1, i);
std::string w(1, *begin++);
std::string result = w;
std::string entry;
for ( ; begin != end; begin++) {
int k = *begin;
if (dictionary.count(k))
entry = dictionary[k];
else if (k == dictSize)
entry = w + w[0];
else
throw "Bad compressed k";
result += entry;
// Add w+entry[0] to the dictionary.
dictionary[dictSize++] = w + entry[0];
w = entry;
}
return result;
}
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> compressed;
compress("TOBEORNOTTOBEORTOBEORNOT", std::back_inserter(compressed));
copy(compressed.begin(), compressed.end(), std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
std::string decompressed = decompress(compressed.begin(), compressed.end());
std::cout << decompressed << std::endl;
return 0;
}

View file

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace LZW
{
public class Program
{
public static void Main(string[] args)
{
List<int> compressed = Compress("TOBEORNOTTOBEORTOBEORNOT");
Console.WriteLine(string.Join(", ", compressed));
string decompressed = Decompress(compressed);
Console.WriteLine(decompressed);
}
public static List<int> Compress(string uncompressed)
{
// build the dictionary
Dictionary<string, int> dictionary = new Dictionary<string, int>();
for (int i = 0; i < 256; i++)
dictionary.Add(((char)i).ToString(), i);
string w = string.Empty;
List<int> compressed = new List<int>();
foreach (char c in uncompressed)
{
string wc = w + c;
if (dictionary.ContainsKey(wc))
{
w = wc;
}
else
{
// write w to output
compressed.Add(dictionary[w]);
// wc is a new sequence; add it to the dictionary
dictionary.Add(wc, dictionary.Count);
w = c.ToString();
}
}
// write remaining output if necessary
if (!string.IsNullOrEmpty(w))
compressed.Add(dictionary[w]);
return compressed;
}
public static string Decompress(List<int> compressed)
{
// build the dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string>();
for (int i = 0; i < 256; i++)
dictionary.Add(i, ((char)i).ToString());
string w = dictionary[compressed[0]];
compressed.RemoveAt(0);
StringBuilder decompressed = new StringBuilder(w);
foreach (int k in compressed)
{
string entry = null;
if (dictionary.ContainsKey(k))
entry = dictionary[k];
else if (k == dictionary.Count)
entry = w + w[0];
decompressed.Append(entry);
// new sequence; add it to the dictionary
dictionary.Add(dictionary.Count, w + entry[0]);
w = entry;
}
return decompressed.ToString();
}
}
}

View file

@ -0,0 +1,258 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
/* -------- aux stuff ---------- */
void* mem_alloc(size_t item_size, size_t n_item)
{
size_t *x = calloc(1, sizeof(size_t)*2 + n_item * item_size);
x[0] = item_size;
x[1] = n_item;
return x + 2;
}
void* mem_extend(void *m, size_t new_n)
{
size_t *x = (size_t*)m - 2;
x = realloc(x, sizeof(size_t) * 2 + *x * new_n);
if (new_n > x[1])
memset((char*)(x + 2) + x[0] * x[1], 0, x[0] * (new_n - x[1]));
x[1] = new_n;
return x + 2;
}
inline void _clear(void *m)
{
size_t *x = (size_t*)m - 2;
memset(m, 0, x[0] * x[1]);
}
#define _new(type, n) mem_alloc(sizeof(type), n)
#define _del(m) { free((size_t*)(m) - 2); m = 0; }
#define _len(m) *((size_t*)m - 1)
#define _setsize(m, n) m = mem_extend(m, n)
#define _extend(m) m = mem_extend(m, _len(m) * 2)
/* ----------- LZW stuff -------------- */
typedef uint8_t byte;
typedef uint16_t ushort;
#define M_CLR 256 /* clear table marker */
#define M_EOD 257 /* end-of-data marker */
#define M_NEW 258 /* new code index */
/* encode and decode dictionary structures.
for encoding, entry at code index is a list of indices that follow current one,
i.e. if code 97 is 'a', code 387 is 'ab', and code 1022 is 'abc',
then dict[97].next['b'] = 387, dict[387].next['c'] = 1022, etc. */
typedef struct {
ushort next[256];
} lzw_enc_t;
/* for decoding, dictionary contains index of whatever prefix index plus trailing
byte. i.e. like previous example,
dict[1022] = { c: 'c', prev: 387 },
dict[387] = { c: 'b', prev: 97 },
dict[97] = { c: 'a', prev: 0 }
the "back" element is used for temporarily chaining indices when resolving
a code to bytes
*/
typedef struct {
ushort prev, back;
byte c;
} lzw_dec_t;
byte* lzw_encode(byte *in, int max_bits)
{
int len = _len(in), bits = 9, next_shift = 512;
ushort code, c, nc, next_code = M_NEW;
lzw_enc_t *d = _new(lzw_enc_t, 512);
if (max_bits > 15) max_bits = 15;
if (max_bits < 9 ) max_bits = 12;
byte *out = _new(ushort, 4);
int out_len = 0, o_bits = 0;
uint32_t tmp = 0;
inline void write_bits(ushort x) {
tmp = (tmp << bits) | x;
o_bits += bits;
if (_len(out) <= out_len) _extend(out);
while (o_bits >= 8) {
o_bits -= 8;
out[out_len++] = tmp >> o_bits;
tmp &= (1 << o_bits) - 1;
}
}
//write_bits(M_CLR);
for (code = *(in++); --len; ) {
c = *(in++);
if ((nc = d[code].next[c]))
code = nc;
else {
write_bits(code);
nc = d[code].next[c] = next_code++;
code = c;
}
/* next new code would be too long for current table */
if (next_code == next_shift) {
/* either reset table back to 9 bits */
if (++bits > max_bits) {
/* table clear marker must occur before bit reset */
write_bits(M_CLR);
bits = 9;
next_shift = 512;
next_code = M_NEW;
_clear(d);
} else /* or extend table */
_setsize(d, next_shift *= 2);
}
}
write_bits(code);
write_bits(M_EOD);
if (tmp) write_bits(tmp);
_del(d);
_setsize(out, out_len);
return out;
}
byte* lzw_decode(byte *in)
{
byte *out = _new(byte, 4);
int out_len = 0;
inline void write_out(byte c)
{
while (out_len >= _len(out)) _extend(out);
out[out_len++] = c;
}
lzw_dec_t *d = _new(lzw_dec_t, 512);
int len, j, next_shift = 512, bits = 9, n_bits = 0;
ushort code, c, t, next_code = M_NEW;
uint32_t tmp = 0;
inline void get_code() {
while(n_bits < bits) {
if (len > 0) {
len --;
tmp = (tmp << 8) | *(in++);
n_bits += 8;
} else {
tmp = tmp << (bits - n_bits);
n_bits = bits;
}
}
n_bits -= bits;
code = tmp >> n_bits;
tmp &= (1 << n_bits) - 1;
}
inline void clear_table() {
_clear(d);
for (j = 0; j < 256; j++) d[j].c = j;
next_code = M_NEW;
next_shift = 512;
bits = 9;
};
clear_table(); /* in case encoded bits didn't start with M_CLR */
for (len = _len(in); len;) {
get_code();
if (code == M_EOD) break;
if (code == M_CLR) {
clear_table();
continue;
}
if (code >= next_code) {
fprintf(stderr, "Bad sequence\n");
_del(out);
goto bail;
}
d[next_code].prev = c = code;
while (c > 255) {
t = d[c].prev; d[t].back = c; c = t;
}
d[next_code - 1].c = c;
while (d[c].back) {
write_out(d[c].c);
t = d[c].back; d[c].back = 0; c = t;
}
write_out(d[c].c);
if (++next_code >= next_shift) {
if (++bits > 16) {
/* if input was correct, we'd have hit M_CLR before this */
fprintf(stderr, "Too many bits\n");
_del(out);
goto bail;
}
_setsize(d, next_shift *= 2);
}
}
/* might be ok, so just whine, don't be drastic */
if (code != M_EOD) fputs("Bits did not end in EOD\n", stderr);
_setsize(out, out_len);
bail: _del(d);
return out;
}
int main()
{
int i, fd = open("unixdict.txt", O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Can't read file\n");
return 1;
};
struct stat st;
fstat(fd, &st);
byte *in = _new(char, st.st_size);
read(fd, in, st.st_size);
_setsize(in, st.st_size);
close(fd);
printf("input size: %d\n", _len(in));
byte *enc = lzw_encode(in, 9);
printf("encoded size: %d\n", _len(enc));
byte *dec = lzw_decode(enc);
printf("decoded size: %d\n", _len(dec));
for (i = 0; i < _len(dec); i++)
if (dec[i] != in[i]) {
printf("bad decode at %d\n", i);
break;
}
if (i == _len(dec)) printf("Decoded ok\n");
_del(in);
_del(enc);
_del(dec);
return 0;
}

View file

@ -0,0 +1,19 @@
(defn make-dict []
(let [vals (range 0 256)]
(zipmap (map (comp #'list #'char) vals) vals)))
(defn compress [#^String text]
(loop [t (seq text)
r '()
w '()
dict (make-dict)
s 256]
(let [c (first t)]
(if c
(let [wc (cons c w)]
(if (get dict wc)
(recur (rest t) r wc dict s)
(recur (rest t) (cons (get dict w) r) (list c) (assoc dict wc s) (inc s))))
(reverse (if w (cons (get dict w) r) r))))))
(compress "TOBEORNOTTOBEORTOBEORNOT")

View file

@ -0,0 +1 @@
(84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263)

View file

@ -0,0 +1,36 @@
lzw = (s) ->
dct = {} # map substrings to codes between 256 and 4096
stream = [] # array of compression results
# initialize basic ASCII characters
for code_num in [0..255]
c = String.fromCharCode(code_num)
dct[c] = code_num
code_num = 256
i = 0
while i < s.length
# Find word and new_word
# word = longest substr already encountered, or next character
# new_word = word plus next character, a new substr to encode
word = ''
j = i
while j < s.length
new_word = word + s[j]
break if !dct[new_word]
word = new_word
j += 1
# stream out the code for the substring
stream.push dct[word]
# build up our encoding dictionary
if code_num < 4096
dct[new_word] = code_num
code_num += 1
# advance thru the string
i += word.length
stream
console.log lzw "TOBEORNOTTOBEORTOBEORNOT"

View file

@ -0,0 +1,110 @@
(declaim (ftype (function (vector vector &optional fixnum fixnum) vector)
vector-append))
(defun vector-append (old new &optional (start2 0) end2)
(declare (optimize (speed 3) (safety 0) (debug 0)))
(prog1 old
(let* ((old-fill (fill-pointer old))
(new-fill (+ old-fill (length new))))
(when (> new-fill (array-dimension old 0))
(adjust-array old (* 4 new-fill)))
(setf (fill-pointer old) new-fill)
(replace old new :start1 old-fill :start2 start2 :end2 end2))))
(declaim (ftype (function (vector t) vector) vector-append1))
(defun vector-append1 (old new)
(prog1 old
(let* ((old-fill (fill-pointer old))
(new-fill (1+ old-fill)))
(when (> new-fill (array-dimension old 0))
(adjust-array old (* 4 new-fill)))
(setf (fill-pointer old) new-fill)
(setf (aref old old-fill) new))))
(declaim (ftype (function (&optional t) vector) make-empty-vector))
(defun make-empty-vector (&optional (element-type t))
(make-array 0 :element-type element-type :fill-pointer 0 :adjustable t))
(declaim (ftype (function (t &optional t) vector) make-vector-with-elt))
(defun make-vector-with-elt (elt &optional (element-type t))
(make-array 1 :element-type element-type
:fill-pointer 1
:adjustable t
:initial-element elt))
(declaim (ftype (function (vector t) vector) vector-append1-new))
(defun vector-append1-new (old new)
(vector-append1 (vector-append (make-empty-vector 'octet) old)
new))
(declaim (ftype (function (vector vector) vector) vector-append-new))
(defun vector-append-new (old new)
(vector-append (vector-append (make-empty-vector 'octet) old)
new))
(deftype octet () '(unsigned-byte 8))
(declaim (ftype (function () hash-table) build-dictionary))
(defun build-dictionary ()
(let ((dictionary (make-hash-table :test #'equalp)))
(loop for i below 256
do (let ((vec (make-vector-with-elt i 'octet)))
(setf (gethash vec dictionary) vec)))
dictionary))
(declaim (ftype (function ((vector octet)) (vector octet))
lzw-compress-octets))
(defun lzw-compress-octets (octets)
(declare (optimize (speed 3) (safety 0) (debug 0)))
(loop with dictionary-size of-type fixnum = 256
with w = (make-empty-vector 'octet)
with result = (make-empty-vector 't)
with dictionary = (build-dictionary)
for c across octets
for wc = (vector-append1-new w c)
if (gethash wc dictionary) do (setq w wc)
else do
(vector-append result (gethash w dictionary))
(setf (gethash wc dictionary)
(make-vector-with-elt dictionary-size))
(incf dictionary-size)
(setq w (make-vector-with-elt c 'octet))
finally (unless (zerop (length (the (vector octet) w)))
(vector-append result (gethash w dictionary)))
(return result)))
(declaim (ftype (function (vector) (vector octet)) lzw-decompress))
(defun #1=lzw-decompress (octets)
(declare (optimize (speed 3) (safety 0) (debug 0)))
(when (zerop (length octets))
(return-from #1# (make-empty-vector 'octet)))
(loop with dictionary-size = 256
with dictionary = (build-dictionary)
with result = (make-vector-with-elt (aref octets 0) 'octet)
with w = (copy-seq result)
for i from 1 below (length octets)
for k = (make-vector-with-elt (aref octets i) 't)
for entry = (or (gethash k dictionary)
(if (equalp k dictionary-size)
(vector-append1-new w (aref w 0))
(error "bad compresed entry at pos ~S" i)))
do (vector-append result entry)
(setf (gethash (make-vector-with-elt dictionary-size) dictionary)
(vector-append1-new w (aref entry 0)))
(incf dictionary-size)
(setq w entry)
finally (return result)))
(defgeneric lzw-compress (datum)
(:method ((string string))
(lzw-compress (babel:string-to-octets string)))
(:method ((octets vector))
(lzw-compress-octets octets)))
(defun lzw-decompress-to-string (octets)
(babel:octets-to-string (lzw-decompress octets)))
(defun test (string)
(assert (equal #2=(lzw-decompress-to-string (lzw-compress string)) string) ()
"Can't compress ~S properly, got ~S instead" string #2#)
t)

View file

@ -0,0 +1,6 @@
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"

View file

@ -0,0 +1,40 @@
import std.stdio, std.array;
auto compress(in string original) pure nothrow {
int[string] dict;
foreach (immutable char c; char.min .. char.max + 1)
dict[[c]] = c;
string w;
int[] result;
foreach (immutable ch; original)
if (w ~ ch in dict)
w = w ~ ch;
else {
result ~= dict[w];
dict[w ~ ch] = dict.length;
w = [ch];
}
return w.empty ? result : (result ~ dict[w]);
}
auto decompress(in int[] compressed) pure nothrow {
auto dict = new string[char.max - char.min + 1];
foreach (immutable char c; char.min .. char.max + 1)
dict[c] = [c];
auto w = dict[compressed[0]];
auto result = w;
foreach (immutable k; compressed[1 .. $]) {
auto entry = (k < dict.length) ? dict[k] : w ~ w[0];
result ~= entry;
dict ~= w ~ entry[0];
w = entry;
}
return result;
}
void main() {
auto comp = "TOBEORNOTTOBEORTOBEORNOT".compress;
writeln(comp, "\n", comp.decompress);
}

View file

@ -0,0 +1,95 @@
struct LZW {
import std.array: empty;
// T is ubyte instead of char because D strings are UTF-8.
alias T = ubyte;
alias Tcomp = ushort;
static assert(Tcomp.sizeof > 1);
alias Ta = immutable(T)[];
enum int initDictSize = 256;
static immutable ubyte[initDictSize] bytes;
static this() {
foreach (immutable T i; 0 .. initDictSize)
bytes[i] = i;
}
static Tcomp[] compress(immutable scope T[] original) pure nothrow @safe
out(result) {
if (!original.empty)
assert(result[0] < initDictSize);
} body {
if (original.empty)
return [];
Tcomp[Ta] dict;
foreach (immutable b; bytes)
dict[[b]] = b;
// Here built-in slices give lower efficiency.
struct Slice {
size_t start, end;
@property opSlice() const pure nothrow @safe @nogc {
return original[start .. end];
}
alias opSlice this;
}
Slice w;
Tcomp[] result;
foreach (immutable i; 0 .. original.length) {
auto wc = Slice(w.start, w.end + 1); // Extend slice.
if (wc in dict) {
w = wc;
} else {
result ~= dict[w];
assert(dict.length < Tcomp.max); // Overflow guard.
dict[wc] = cast(Tcomp)dict.length;
w = Slice(i, i + 1);
}
}
if (!w.empty)
result ~= dict[w];
return result;
}
static Ta decompress(in Tcomp[] compressed) pure @safe
in {
if (!compressed.empty)
assert(compressed[0] < initDictSize, "Bad compressed");
} body {
if (compressed.empty)
return [];
auto dict = new Ta[initDictSize];
foreach (immutable b; bytes)
dict[b] = [b];
auto w = dict[compressed[0]];
auto result = w;
foreach (immutable k; compressed[1 .. $]) {
Ta entry;
if (k < dict.length)
entry = dict[k];
else if (k == dict.length)
entry = w ~ w[0];
else
throw new Exception("Bad compressed k.");
result ~= entry;
dict ~= w ~ entry[0];
w = entry;
}
return result;
}
}
void main() {
import std.stdio, std.string;
immutable txt = "TOBEORNOTTOBEORTOBEORNOT";
immutable compressed = LZW.compress(txt.representation);
compressed.writeln;
LZW.decompress(compressed).assumeUTF.writeln;
}

View file

@ -0,0 +1,222 @@
enum Marker: ushort {
CLR = 256, // Clear table marker.
EOD = 257, // End-of-data marker.
NEW = 258 // New code index.
}
ubyte[] lzwEncode(scope const(ubyte)[] inp, in uint maxBits) pure nothrow
in {
assert(maxBits >= 9 && maxBits <= 16);
} body {
// Encode dictionary array. For encoding, entry at
// code index is a list of indices that follow current one,
// i.e. if code 97 is 'a', code 387 is 'ab', and code 1022 is 'abc',
// then dict[97].next['b'] = 387, dict[387].next['c'] = 1022, etc.
alias LZWenc = ushort[256];
auto len = inp.length;
uint bits = 9;
auto d = new LZWenc[512];
auto result = new ubyte[16];
size_t outLen = 0;
size_t oBits = 0;
uint tmp = 0;
void writeBits(in ushort x) nothrow {
tmp = (tmp << bits) | x;
oBits += bits;
if (result.length / 2 <= outLen)
result.length *= 2;
while (oBits >= 8) {
oBits -= 8;
assert(tmp >> oBits <= ubyte.max);
result[outLen] = cast(ubyte)(tmp >> oBits);
outLen++;
tmp &= (1 << oBits) - 1;
}
}
// writeBits(Marker.CLR);
ushort nextCode = Marker.NEW;
uint nextShift = 512;
ushort code = inp[0];
inp = inp[1 .. $]; // popFront.
while (--len) {
ushort c = inp[0];
inp = inp[1 .. $]; // popFront.
ushort nc = d[code][c];
if (nc) {
code = nc;
} else {
writeBits(code);
nc = d[code][c] = nextCode;
nextCode++;
code = c;
}
// Next new code would be too long for current table.
if (nextCode == nextShift) {
// Either reset table back to 9 bits.
bits++;
if (bits > maxBits) {
// Table clear marker must occur before bit reset.
writeBits(Marker.CLR);
bits = 9;
nextShift = 512;
nextCode = Marker.NEW;
d[] = LZWenc.init;
} else { // Or extend table.
nextShift *= 2;
d.length = nextShift;
}
}
}
writeBits(code);
writeBits(Marker.EOD);
if (tmp) {
assert(tmp <= ushort.max);
writeBits(cast(ushort)tmp);
}
return result[0 .. outLen];
}
ubyte[] lzwDecode(scope const(ubyte)[] inp) pure {
// For decoding, dictionary contains index of whatever prefix
// index plus trailing ubyte. i.e. like previous example,
// dict[1022] = { c: 'c', prev: 387 },
// dict[387] = { c: 'b', prev: 97 },
// dict[97] = { c: 'a', prev: 0 }
// the "back" element is used for temporarily chaining indices
// when resolving a code to bytes.
static struct LZWdec {
ushort prev, back;
ubyte c;
}
auto result = new ubyte[4];
uint outLen = 0;
void writeOut(in ubyte c) nothrow {
while (outLen >= result.length)
result.length *= 2;
result[outLen] = c;
outLen++;
}
auto d = new LZWdec[512];
ushort code = 0;
uint bits = 9;
uint len = 0;
uint nBits = 0;
uint tmp = 0;
void getCode() nothrow {
while (nBits < bits) {
if (len > 0) {
len--;
tmp = (tmp << 8) | inp[0];
inp = inp[1 .. $]; // popFront.
nBits += 8;
} else {
tmp = tmp << (bits - nBits);
nBits = bits;
}
}
nBits -= bits;
assert(tmp >> nBits <= ushort.max);
code = cast(ushort)(tmp >> nBits);
tmp &= (1 << nBits) - 1;
}
uint nextShift = 512;
ushort nextCode = Marker.NEW;
void clearTable() nothrow {
d[] = LZWdec.init;
foreach (immutable ubyte j; 0 .. 256)
d[j].c = j;
nextCode = Marker.NEW;
nextShift = 512;
bits = 9;
}
clearTable(); // In case encoded bits didn't start with Marker.CLR.
for (len = inp.length; len;) {
getCode();
if (code == Marker.EOD)
break;
if (code == Marker.CLR) {
clearTable();
continue;
}
if (code >= nextCode)
throw new Error("Bad sequence.");
auto c = code;
d[nextCode].prev = c;
while (c > 255) {
immutable t = d[c].prev;
d[t].back = c;
c = t;
}
assert(c <= ubyte.max);
d[nextCode - 1].c = cast(ubyte)c;
while (d[c].back) {
writeOut(d[c].c);
immutable t = d[c].back;
d[c].back = 0;
c = t;
}
writeOut(d[c].c);
nextCode++;
if (nextCode >= nextShift) {
bits++;
if (bits > 16) {
// If input was correct, we'd have hit Marker.CLR before this.
throw new Error("Too many bits.");
}
nextShift *= 2;
d.length = nextShift;
}
}
// Might be OK, so throw just an exception.
if (code != Marker.EOD)
throw new Exception("Bits did not end in EOD");
return result[0 .. outLen];
}
void main() {
import std.stdio, std.file;
const inputData = cast(ubyte[])read("unixdict.txt");
writeln("Input size: ", inputData.length);
immutable encoded = lzwEncode(inputData, 12);
writeln("Encoded size: ", encoded.length);
immutable decoded = lzwDecode(encoded);
writeln("Decoded size: ", decoded.length);
if (inputData.length != decoded.length)
return writeln("Error: decoded size differs");
foreach (immutable i, immutable x; inputData)
if (x != decoded[i])
return writeln("Bad decode at ", i);
"Decoded OK.".writeln;
}

View file

@ -0,0 +1,43 @@
Module: LZW
Synopsis: LZW implementation for Rosetta code
define method output(n :: <integer>)
format-out("%d ", n);
end;
define method contains?(dict, var)
let x = element(dict, var, default: #f);
x ~= #f;
end;
define method byte->string(c)
add("", as(<character>, c));
end;
define method compress(input :: <string>) => <vector>;
let result = make(<vector>);
let dict = make(<string-table>);
for (x from 0 to 255)
dict[byte->string(x)] := x;
end;
let next-code = 256;
let cur-seq = "";
for (c in input)
let wc = add(cur-seq, c);
if (contains?(dict, wc))
cur-seq := wc;
else
result := add(result, dict[cur-seq]);
dict[wc] := next-code;
next-code := next-code + 1;
cur-seq := add("", c);
end
end;
unless (empty?(cur-seq))
result := add(result, dict[cur-seq]);
end;
result
end;
format-out("%=\n", compress("TOBEORNOTTOBEORTOBEORNOT"))

View file

@ -0,0 +1,40 @@
fun compress = List by text uncompressed
Map dictionary = text%int[].with(256, <int i|text%int(chr(i) => i))
text w
List result = int[]
for each text c in uncompressed
text wc = w + c
if dictionary.has(wc)
w = wc
else
result.append(dictionary[w])
dictionary.insert(wc, dictionary.length)
w = c
end
end
if not w.isEmpty() do result.append(dictionary[w]) end
return result
end
fun decompress = text by List compressed
Map dictionary = int%text[].with(256, <int i|int%text(i => chr(i)))
text w = chr(compressed[0])
text result = *w
for each int k in compressed.extract(1)
text entry
if dictionary.has(k)
entry = dictionary[k]
else if k == dictionary.length
entry = w + w[0]
else
error(65, "Error decompressing")
end
result.append(entry)
dictionary.insert(dictionary.length, w + entry[0])
w = entry
end
return result
end
List compressed = compress("TOBEORNOTTOBEORTOBEORNOT")
writeLine(compressed)
text decompressed = decompress(compressed)
writeLine(decompressed)

View file

@ -0,0 +1,112 @@
class
APPLICATION
create
make
feature {NONE}
make
local
test: LINKED_LIST [INTEGER]
do
create test.make
test := compress ("TOBEORNOTTOBEORTOBEORNOT")
across
test as t
loop
io.put_string (t.item.out + " ")
end
io.new_line
io.put_string (decompress (test))
end
decompress (compressed: LINKED_LIST [INTEGER]): STRING
--Decompressed version of 'compressed'.
local
dictsize, i, k: INTEGER
dictionary: HASH_TABLE [STRING, INTEGER]
w, entry: STRING
char: CHARACTER_8
do
dictsize := 256
create dictionary.make (300)
create entry.make_empty
create Result.make_empty
from
i := 0
until
i > 256
loop
char := i.to_character_8
dictionary.put (char.out, i)
i := i + 1
end
w := compressed.first.to_character_8.out
compressed.go_i_th (1)
compressed.remove
Result := w
from
k := 1
until
k > compressed.count
loop
if attached dictionary.at (compressed [k]) as ata then
entry := ata
elseif compressed [k] = dictsize then
entry := w + w.at (1).out
else
io.put_string ("EXEPTION")
end
Result := Result + entry
dictsize := dictsize + 1
dictionary.put (w + entry.at (1).out, dictsize)
w := entry
k := k + 1
end
end
compress (uncompressed: STRING): LINKED_LIST [INTEGER]
-- Compressed version of 'uncompressed'.
local
dictsize: INTEGER
dictionary: HASH_TABLE [INTEGER, STRING]
i: INTEGER
w, wc: STRING
char: CHARACTER_8
do
dictsize := 256
create dictionary.make (256)
create w.make_empty
from
i := 0
until
i > 256
loop
char := i.to_character_8
dictionary.put (i, char.out)
i := i + 1
end
create Result.make
from
i := 1
until
i > uncompressed.count
loop
wc := w + uncompressed [i].out
if dictionary.has (wc) then
w := wc
else
Result.extend (dictionary.at (w))
dictSize := dictSize + 1
dictionary.put (dictSize, wc)
w := "" + uncompressed [i].out
end
i := i + 1
end
if w.count > 0 then
Result.extend (dictionary.at (w))
end
end
end

View file

@ -0,0 +1,39 @@
defmodule LZW do
@encode_map Enum.into(0..255, Map.new, &{[&1],&1})
@decode_map Enum.into(0..255, Map.new, &{&1,[&1]})
def encode(str), do: encode(to_char_list(str), @encode_map, 256, [])
defp encode([h], d, _, out), do: Enum.reverse([d[[h]] | out])
defp encode([h|t], d, free, out) do
val = d[[h]]
find_match(t, [h], val, d, free, out)
end
defp find_match([h|t], l, lastval, d, free, out) do
case Map.fetch(d, [h|l]) do
{:ok, val} -> find_match(t, [h|l], val, d, free, out)
:error -> d1 = Map.put(d, [h|l], free)
encode([h|t], d1, free+1, [lastval | out])
end
end
defp find_match([], _, lastval, _, _, out), do: Enum.reverse([lastval | out])
def decode([h|t]) do
val = @decode_map[h]
decode(t, val, 256, @decode_map, val)
end
defp decode([], _, _, _, l), do: Enum.reverse(l) |> to_string
defp decode([h|t], old, free, d, l) do
val = if h == free, do: old ++ [List.first(old)], else: d[h]
add = [List.last(val) | old]
d1 = Map.put(d, free, add)
decode(t, val, free+1, d1, val++l)
end
end
str = "TOBEORNOTTOBEORTOBEORNOT"
IO.inspect enc = LZW.encode(str)
IO.inspect dec = LZW.decode(enc)
IO.inspect str == dec

View file

@ -0,0 +1,57 @@
-module(lzw).
-export([test/0, encode/1, decode/1]).
-import(lists, [reverse/1, reverse/2]).
test() ->
Str = "TOBEORNOTTOBEORTOBEORNOT",
[84,79,66,69,79,82,78,79,84,256,258,260,265,259,261,263] =
encode(Str),
Str = decode(encode(Str)),
ok.
encode(Str) ->
D = init(dict:new()),
encode(Str, D, 256, []).
encode([H], D, _, Out) ->
Val = dict:fetch([H], D),
reverse([Val|Out]);
encode([H|T], D, Free, Out) ->
Val = dict:fetch([H], D),
find_match(T, [H], Val, D, Free, Out).
find_match([H|T], L, LastVal, D, Free, Out) ->
case dict:find([H|L], D) of
{ok, Val} ->
find_match(T, [H|L], Val, D, Free, Out);
error ->
D1 = dict:store([H|L], Free, D),
encode([H|T], D1, Free+1, [LastVal|Out])
end;
find_match([], _, LastVal, _, _, Out) ->
reverse([LastVal|Out]).
decode([H|T]) ->
D = init1(dict:new()),
Val = dict:fetch(H, D),
decode(T, Val, 256, D, Val).
decode([], _, _, _, L) ->
reverse(L);
decode([H|T], Old, Free, D, L) ->
Val = dict:fetch(H, D),
Add = [lists:last(Val)|Old],
D1 = dict:store(Free, Add, D),
decode(T, Val, Free+1, D1, Val ++ L).
init(D) -> init(255, D).
init(0, D) -> D;
init(N, D) -> D1 = dict:store([N],N,D), init(N-1, D1).
init1(D) -> init1(255, D).
init1(0, D) -> D;
init1(N, D) -> D1 = dict:store(N,[N],D), init1(N-1, D1).

View file

@ -0,0 +1,99 @@
256 value next-symbol
\ current string fragment
create w 256 allot \ counted string
: w=c ( c -- ) w 1+ c! 1 w c! ;
: w+c ( c -- ) w count + c! w c@ 1+ w c! ;
\ Compression
\ dictionary of strings to symbols
0 value dict
: init-dict table to dict 256 to next-symbol dict set-current ;
: free-dict forth-wordlist set-current ;
: in-dict? ( key len -- ? ) \ can assume len > 1
dict search-wordlist dup if nip then ;
: lookup-dict ( key len -- symbol )
dup 1 = if drop c@ exit then
dict search-wordlist if >body @ else abort" bad-dict!" then ;
: put-dict ( data key len -- )
nextname create , ;
\ output buffer of symbols
\ in real life, these symbols would be packed into octets
variable out-size
create out 256 cells allot
: output ( symbol -- )
dup out out-size @ cells + ! 1 out-size +!
dup 256 < if emit space else . then ;
: compress ( addr len -- )
init-dict 0 out-size !
over c@ w=c 1 /string
bounds do
i c@ w+c
w count in-dict? 0= if
w count 1- lookup-dict output
next-symbol dup w count put-dict
1+ to next-symbol
i c@ w=c
then
loop
w count lookup-dict output
free-dict ;
\ Decompression
\ array of symbols to strings (in real code this would need to be growable)
\ next-symbol is reused for the size of this table
create symtab 256 cells allot
0 value start
: init-symtab 256 to next-symbol here to start ;
: free-symtab start here - allot ;
: get-symbol ( symbol -- addr len )
dup 256 < if pad c! pad 1 exit then
256 - cells symtab + @ count ;
: add-symbol ( addr len -- )
here symtab next-symbol 256 - cells + !
s,
next-symbol 1+ to next-symbol ;
create entry 256 allot
: decompress ( addr len -- )
init-symtab
over @ dup emit w=c
cells bounds cell+ do
i @ next-symbol < if
i @ get-symbol entry place
else i @ next-symbol = if
w 1+ c@ w count + c! w count 1+ entry place
else
abort" bad symbol!"
then then
entry count type \ output
entry 1+ c@ w+c
w count add-symbol
entry count w place
1 cells +loop
free-symtab ;
\ Testing
s" TOBEORNOTTOBEORTOBEORNOT" compress cr
\ T O B E O R N O T 256 258 260 265 259 261 263
out out-size @ decompress cr
\ TOBEORNOTTOBEORTOBEORNOT

View file

@ -0,0 +1,422 @@
!
! lzw_shared_parameters.f90
!
! LZW Common Variables Used by Coder and Decoder
!
! Author: Pedro Garcia Freitas <sawp@sawp.com.br>
! May, 2011
!
! License: Creative Commons http://creativecommons.org/licenses/by-nc-nd/3.0/
!
MODULE LZW_SHARED_PARAMETERS
IMPLICIT NONE
!
! PARAMETER definitions
!
INTEGER , PARAMETER :: COMPILER_INTEGER_SIZE = 32 , BITS = 12 , FILEIN = 66 , &
& FILEOUT = 99 , MAX_VALUE = (2**BITS) - 1 , &
& MAX_CODE = MAX_VALUE - 1 , MAX_DICTIONARY_SIZE = 5021 , &
& SYMBOL_SIZE = 8 , MISSING_BITS = COMPILER_INTEGER_SIZE - &
& SYMBOL_SIZE
!
! Local variables
!
INTEGER , DIMENSION(0:MAX_DICTIONARY_SIZE) :: concatenatedsymbols
INTEGER , DIMENSION(0:MAX_DICTIONARY_SIZE) :: prefixcodes
INTEGER :: the_status = 0
! change this if compiler dont use 32 bits for integer
END MODULE LZW_SHARED_PARAMETERS
!
! codecIO.f90
!
! bit IO routines for coder and encoder.
!
! Author: Pedro Garcia Freitas <sawp@sawp.com.br>
! May, 2011
!
! License: Creative Commons http://creativecommons.org/licenses/by-nc-nd/3.0/
!
MODULE CODECIO
USE LZW_SHARED_PARAMETERS
IMPLICIT NONE
!
CONTAINS
SUBROUTINE SETOUTPUTCODE(Code)
IMPLICIT NONE
!
! Dummy arguments
!
INTEGER :: Code
INTENT (IN) Code
!
! Local variables
!
INTEGER :: buffer
INTEGER :: outputbitbuffer = 0
INTEGER :: outputbitcount = 0
INTEGER :: shift
INTEGER :: shiftedsymbol
!
shift = COMPILER_INTEGER_SIZE - BITS - outputbitcount
shiftedsymbol = ISHFT(Code , shift)
outputbitbuffer = IOR(outputbitbuffer , shiftedsymbol)
outputbitcount = outputbitcount + BITS
DO WHILE(outputbitcount >= SYMBOL_SIZE)
! IF( outputbitcount<SYMBOL_SIZE )EXIT
buffer = ISHFT(outputbitbuffer , -MISSING_BITS)
CALL SETRAWBYTE(buffer)
outputbitbuffer = ISHFT(outputbitbuffer , SYMBOL_SIZE)
outputbitcount = outputbitcount - SYMBOL_SIZE
END DO
RETURN
END SUBROUTINE SETOUTPUTCODE
SUBROUTINE SETRAWBYTE(Symbol)
IMPLICIT NONE
!
! Dummy arguments
!
INTEGER :: Symbol
INTENT (IN) Symbol
!
CALL FPUTC(FILEOUT , ACHAR(Symbol))
END SUBROUTINE SETRAWBYTE
FUNCTION GETRAWBYTE()
IMPLICIT NONE
!
! Dummy arguments
!
INTEGER :: GETRAWBYTE
!
! Local variables
!
CHARACTER :: bufferedbyte
!
CALL FGETC(FILEIN , bufferedbyte , THE_status)
GETRAWBYTE = IACHAR(bufferedbyte)
END FUNCTION GETRAWBYTE
FUNCTION GETINPUTCODE()
IMPLICIT NONE
!
! Dummy arguments
!
INTEGER :: GETINPUTCODE
!
! Local variables
!
INTEGER :: inputbitbuffer = 0
INTEGER :: inputbitcounter = 0
INTEGER :: integerinputbuff
INTEGER :: returnn
INTEGER :: shiftedbit
!
DO WHILE( inputbitcounter <= MISSING_BITS )
! IF( inputbitcounter>MISSING_BITS )EXIT
integerinputbuff = GETRAWBYTE()
shiftedbit = ISHFT(integerinputbuff , MISSING_BITS - inputbitcounter)
inputbitbuffer = IOR(inputbitbuffer , shiftedbit)
inputbitcounter = inputbitcounter + SYMBOL_SIZE
END DO
returnn = ISHFT(inputbitbuffer , BITS - COMPILER_INTEGER_SIZE)
inputbitbuffer = ISHFT(inputbitbuffer , BITS)
inputbitcounter = inputbitcounter - BITS
GETINPUTCODE = returnn
RETURN
END FUNCTION GETINPUTCODE
end module codecIO
! lzw_encoder.f90
!
! LZW Coder (Compressor)
!
! Author: Pedro Garcia Freitas <sawp@sawp.com.br>
! May, 2011
!
! License: Creative Commons http://creativecommons.org/licenses/by-nc-nd/3.0/
!
MODULE LZW_ENCODER
USE LZW_SHARED_PARAMETERS
USE CODECIO
IMPLICIT NONE
!
! PARAMETER definitions
!
INTEGER , PARAMETER :: HASH_SHIFT = BITS - SYMBOL_SIZE
!
! Local variables
!
INTEGER , DIMENSION(0:MAX_DICTIONARY_SIZE) :: symbolvalues
CONTAINS
SUBROUTINE COMPRESS()
IMPLICIT NONE
!
! Local variables
!
INTEGER :: codedsymbol
INTEGER :: my_index
INTEGER :: nextsymbol
INTEGER :: symbol
CHARACTER :: bufferedbyte
!
nextsymbol = COMPILER_INTEGER_SIZE*SYMBOL_SIZE
SYMbolvalues(:) = -1
! codedsymbol = GETRAWBYTE()
CALL FGETC(FILEIN , bufferedbyte , THE_status)
codedsymbol = IACHAR(bufferedbyte)
!Can be hand optimized - optimization
DO WHILE(THE_status == 0)
! symbol = GETRAWBYTE() ! Manual inline of function
CALL FGETC(FILEIN , bufferedbyte , THE_status)
symbol = IACHAR(bufferedbyte)
IF( THE_status/=0 )CYCLE
my_index = GETPOSITIONONDICTIONARY(codedsymbol , symbol)
IF( SYMbolvalues(my_index)/= - 1 )THEN
codedsymbol = SYMbolvalues(my_index)
ELSE
IF( nextsymbol<=MAX_CODE )THEN
SYMbolvalues(my_index) = nextsymbol
nextsymbol = nextsymbol + 1
PREfixcodes(my_index) = codedsymbol
CONcatenatedsymbols(my_index) = symbol
END IF
CALL SETOUTPUTCODE(codedsymbol)
codedsymbol = symbol
END IF
END DO
CALL SETOUTPUTCODE(codedsymbol)
CALL SETOUTPUTCODE(MAX_VALUE)
CALL SETOUTPUTCODE(0)
END SUBROUTINE COMPRESS
function getPositionOnDictionary(hashPrefix, hashSymbol)
integer, intent(in) :: hashPrefix
integer, intent(in) :: hashSymbol
integer :: getPositionOnDictionary
integer :: index
integer :: offset
index = ishft(hashSymbol, HASH_SHIFT)
index = ieor(index, hashPrefix)
if (index == 0) then
offset = 1
else
offset = MAX_DICTIONARY_SIZE - index
endif
do
if (symbolValues(index) == -1) then
getPositionOnDictionary = index
exit
endif
if (prefixCodes(index) == hashPrefix .and. &
& concatenatedSymbols(index) == hashSymbol) then
getPositionOnDictionary = index
exit
endif
index = index - offset
if (index < 0) then
index = index + MAX_DICTIONARY_SIZE
endif
end do
return
end function
end module LZW_Encoder
! lzw_decoder.f90
!
! LZW Decoder (Expanssor)
!
! Author: Pedro Garcia Freitas <sawp@sawp.com.br>
! May, 2011
!
! License: Creative Commons http://creativecommons.org/licenses/by-nc-nd/3.0/
!
MODULE LZW_DECODER
USE LZW_SHARED_PARAMETERS
USE CODECIO
IMPLICIT NONE
!
! Derived Type definitions
!
TYPE :: DECODE_BUFFER_STACK
INTEGER , DIMENSION(0:MAX_DICTIONARY_SIZE) :: DECODERSTACK
INTEGER :: TOP
END TYPE DECODE_BUFFER_STACK
!
! Local variables
!
TYPE(DECODE_BUFFER_STACK) :: stack
CONTAINS
!
! Can be hand optimized - optimization
SUBROUTINE DECOMPRESS()
IMPLICIT NONE
!
! Local variables
!
INTEGER :: newsymbol
INTEGER :: nextsymbol
INTEGER :: oldsymbol
INTEGER :: popedsymbol
INTEGER :: symbol
!
nextsymbol = COMPILER_INTEGER_SIZE*SYMBOL_SIZE
oldsymbol = GETINPUTCODE()
symbol = oldsymbol
CALL SETRAWBYTE(oldsymbol)
DO
newsymbol = GETINPUTCODE()
IF( newsymbol==MAX_VALUE )RETURN
IF( newsymbol>=nextsymbol )THEN
STAck%DECODERSTACK(0) = symbol
CALL DECODESYMBOL(STAck%DECODERSTACK(1:) , oldsymbol)
ELSE
CALL DECODESYMBOL(STAck%DECODERSTACK(:) , newsymbol)
END IF
symbol = STAck%DECODERSTACK(STAck%TOP)
DO WHILE ( STAck%TOP>=0 )
popedsymbol = STAck%DECODERSTACK(STAck%TOP)
CALL SETRAWBYTE(popedsymbol)
STAck%TOP = STAck%TOP - 1
END DO
IF( nextsymbol<=MAX_CODE )THEN
PREfixcodes(nextsymbol) = oldsymbol
CONcatenatedsymbols(nextsymbol) = symbol
nextsymbol = nextsymbol + 1
END IF
oldsymbol = newsymbol
END DO
RETURN
END SUBROUTINE DECOMPRESS
SUBROUTINE DECODESYMBOL(Buffer , Code)
IMPLICIT NONE
!
! Dummy arguments
!
INTEGER :: Code
INTEGER , DIMENSION(:) :: Buffer
INTENT (IN) Code
INTENT (INOUT) Buffer
!
! Local variables
!
INTEGER :: i
INTEGER :: j
INTEGER :: symbol
!
j = 0
symbol = Code
STAck%TOP = 0
DO WHILE ( symbol>=COMPILER_INTEGER_SIZE*SYMBOL_SIZE )
! IF( symbol<COMPILER_INTEGER_SIZE*SYMBOL_SIZE )EXIT
IF( j>=MAX_CODE )THEN
PRINT * , "Decoding error"
STOP
END IF
i = STAck%TOP + 1
Buffer(i) = CONcatenatedsymbols(symbol)
symbol = PREfixcodes(symbol)
STAck%TOP = STAck%TOP + 1
j = j + 1
END DO
i = j + 1
Buffer(i) = symbol
END SUBROUTINE DECODESYMBOL
end module LZW_Decoder
! lzw.f90
!
! LZW Coder and Decoder
!
! Author: Pedro Garcia Freitas <sawp@sawp.com.br>
! May, 2011
!
! License: Creative Commons http://creativecommons.org/licenses/by-nc-nd/3.0/
!
MODULE LZW
USE LZW_SHARED_PARAMETERS
USE LZW_ENCODER
USE LZW_DECODER
IMPLICIT NONE
CONTAINS
SUBROUTINE INIT(Input , Output , Operation , Filename)
IMPLICIT NONE
!
! Dummy arguments
!
CHARACTER(100) :: Filename
CHARACTER(100) :: Input
CHARACTER(1) :: Operation
CHARACTER(100) :: Output
INTENT (IN) Filename , Input , Operation , Output
!
IF( Operation/='d' .AND. Operation/='e' )THEN
PRINT * , "Usage: " // TRIM(Filename) // " <operation> input output"
PRINT * , "Possible operations: "
PRINT * , " e -> encode (compress)"
PRINT * , " d -> decode (inflate)"
STOP
END IF
OPEN(UNIT = FILEIN , FILE = Input , ACTION = "read" , STATUS = "old" , &
&ACCESS = 'stream' , FORM = "formatted")
OPEN(UNIT = FILEOUT , FILE = Output , ACTION = "write" , STATUS = "replace" , &
& ACCESS = 'stream' , FORM = "formatted")
IF( Operation=='d' )THEN
PRINT * , "Decoding..."
CALL DECOMPRESS()
ELSE
PRINT * , "Encoding..."
CALL COMPRESS()
END IF
CLOSE(UNIT = FILEIN)
CLOSE(UNIT = FILEOUT)
END SUBROUTINE INIT
end module LZW
!
PROGRAM MAIN
USE LZW
IMPLICIT NONE
!
! Local variables
!
CHARACTER(100) :: filename
REAL :: finish
CHARACTER(100) :: input
CHARACTER(1) :: operation
CHARACTER(100) :: output
REAL :: start
!
CALL GETARG(0 , filename)
CALL GETARG(1 , operation)
CALL GETARG(2 , input)
CALL GETARG(3 , output)
CALL CPU_TIME(start)
CALL INIT(input , output , operation , filename)
CALL CPU_TIME(finish)
PRINT '("Time = ",f6.3," seconds.")' , finish - start
END PROGRAM MAIN

View file

@ -0,0 +1,110 @@
' version 22-02-2019
' compile with: fbc -s console
Type dict
prefix As Integer
B As String
End Type
Sub init(dictionary() As dict, ByRef last As ULong)
For i As ULong = 0 To 255
dictionary(i).prefix = -1
dictionary(i).B = Chr(i)
Next
last = 255
End Sub
Function encode_LZW(dictionary() As dict, last_entry As ULong, input_str As String) As String
If Len(input_str) < 2 Then
Print "input string is to short"
Return ""
End If
Dim As String word, output_str, char
Dim As ULong i = 1, index, j, len_input = Len(input_str)
Do
If i > len_input Then
output_str = output_str + " " + Str(index)
Return output_str ' no more chars to process. we are done
End If
char = Mid(Input_str, i, 1)
i += 1
For j = 0 To last_entry
If dictionary(j).B = word + char Then
word += char
index = j
Continue Do
End If
Next
output_str = output_str + " " + Str(index)
last_entry = last_entry +1
dictionary(last_entry).B = word + char
dictionary(last_entry).prefix = index
word = char : index = Asc(char)
Loop
End Function
Function decode_LZW(dictionary() As dict, last_entry As ULong, input_str As String) As String
Dim As String temp, word, output_str
Dim As ULong i, i1 = 1, j, index
input_str = Trim(input_str)
Dim As ULong len_input = Len(input_str)
input_str = input_str + " "
i = InStr(i1, input_str, " ")
index = Val(Mid(Input_str, i1, i - i1))
word = dictionary(index).B
output_str = word
i1 = i +1
Do
i = InStr(i1, input_str, " ")
If i >= len_input Then
index = Val(Mid(input_str, i1))
output_str = output_str + dictionary(index).B
Return output_str
End If
index = Val(Mid(Input_str, i1, i - i1))
i1 = i +1
If index <= last_entry Then
temp = dictionary(index).B
Else
temp = word + Left(word, 1)
End If
output_str = output_str + temp
last_entry = last_entry +1
dictionary(last_entry).B = word + Left(temp, 1)
word = temp
Loop
End Function
' ------=< MAIN >=------
Dim As ULong last_entry, max_bit = 9
Dim As ULong dict_max = 1 Shl max_bit -1
Dim As String output_str, input_str = "TOBEORNOTTOBEORTOBEORNOT"
Dim As dict dictionary()
Print " input str: ";input_str
ReDim dictionary(dict_max +1)
init(dictionary(), last_entry)
output_str = encode_LZW(dictionary(), last_entry, input_str)
Print "encoded str: ";output_str
ReDim dictionary(dict_max +1)
init(dictionary(), last_entry)
output_str = decode_LZW(dictionary(), last_entry, output_str)
Print "decoded str: "; output_str
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -0,0 +1,95 @@
package main
import (
"fmt"
"log"
"strings"
)
// Compress a string to a list of output symbols.
func compress(uncompressed string) []int {
// Build the dictionary.
dictSize := 256
// We actually want a map of []byte -> int but
// slices are not acceptable map key types.
dictionary := make(map[string]int, dictSize)
for i := 0; i < dictSize; i++ {
// Ugly mess to work around not having a []byte key type.
// Using `string(i)` would do utf8 encoding for i>127.
dictionary[string([]byte{byte(i)})] = i
}
var result []int
var w []byte
for i := 0; i < len(uncompressed); i++ {
c := uncompressed[i]
wc := append(w, c)
if _, ok := dictionary[string(wc)]; ok {
w = wc
} else {
result = append(result, dictionary[string(w)])
// Add wc to the dictionary.
dictionary[string(wc)] = dictSize
dictSize++
//w = []byte{c}, but re-using wc
wc[0] = c
w = wc[:1]
}
}
if len(w) > 0 {
// Output the code for w.
result = append(result, dictionary[string(w)])
}
return result
}
type BadSymbolError int
func (e BadSymbolError) Error() string {
return fmt.Sprint("Bad compressed symbol ", int(e))
}
// Decompress a list of output symbols to a string.
func decompress(compressed []int) (string, error) {
// Build the dictionary.
dictSize := 256
dictionary := make(map[int][]byte, dictSize)
for i := 0; i < dictSize; i++ {
dictionary[i] = []byte{byte(i)}
}
var result strings.Builder
var w []byte
for _, k := range compressed {
var entry []byte
if x, ok := dictionary[k]; ok {
//entry = x, but ensuring any append will make a copy
entry = x[:len(x):len(x)]
} else if k == dictSize && len(w) > 0 {
entry = append(w, w[0])
} else {
return result.String(), BadSymbolError(k)
}
result.Write(entry)
if len(w) > 0 {
// Add w+entry[0] to the dictionary.
w = append(w, entry[0])
dictionary[dictSize] = w
dictSize++
}
w = entry
}
return result.String(), nil
}
func main() {
compressed := compress("TOBEORNOTTOBEORTOBEORNOT")
fmt.Println(compressed)
decompressed, err := decompress(compressed)
if err != nil {
log.Fatal(err)
}
fmt.Println(decompressed)
}

View file

@ -0,0 +1,37 @@
def compress = { text ->
def dictionary = (0..<256).inject([:]) { map, ch -> map."${(char)ch}" = ch; map }
def w = '', compressed = []
text.each { ch ->
def wc = "$w$ch"
if (dictionary[wc]) {
w = wc
} else {
compressed << dictionary[w]
dictionary[wc] = dictionary.size()
w = "$ch"
}
}
if (w) { compressed << dictionary[w] }
compressed
}
def decompress = { compressed ->
def dictionary = (0..<256).inject([:]) { map, ch -> map[ch] = "${(char)ch}"; map }
int dictSize = 128;
String w = "${(char)compressed[0]}"
StringBuffer result = new StringBuffer(w)
compressed.drop(1).each { k ->
String entry = dictionary[k]
if (!entry) {
if (k != dictionary.size()) throw new IllegalArgumentException("Bad compressed k $k")
entry = "$w${w[0]}"
}
result << entry
dictionary[dictionary.size()] = "$w${entry[0]}"
w = entry
}
result.toString()
}

View file

@ -0,0 +1,8 @@
def plaintext = 'TOBEORNOTTOBEORTOBEORNOT'
def compressed = compress(plaintext)
def result = decompress(compressed)
println """\
Plaintext: '$plaintext'
Compressed: $compressed
Uncompressed: '$result'""".stripIndent()

View file

@ -0,0 +1,38 @@
import Data.List (elemIndex, tails)
import Data.Maybe (fromJust)
doLZW :: Eq a => [a] -> [a] -> [Int]
doLZW _ [] = []
doLZW as (x:xs) = lzw (return <$> as) [x] xs
where
lzw a w [] = [fromJust $ elemIndex w a]
lzw a w (x:xs)
| w_ `elem` a = lzw a w_ xs
| otherwise = fromJust (elemIndex w a) : lzw (a ++ [w_]) [x] xs
where
w_ = w ++ [x]
undoLZW :: [a] -> [Int] -> [a]
undoLZW _ [] = []
undoLZW a cs =
cs >>=
(!!)
(foldl
((.) <$> (++) <*>
(\x xs -> return (((++) <$> head <*> take 1 . last) ((x !!) <$> xs))))
(return <$> a)
(take2 cs))
take2 :: [a] -> [[a]]
take2 xs = filter ((2 ==) . length) (take 2 <$> tails xs)
main :: IO ()
main = do
print $ doLZW ['\0' .. '\255'] "TOBEORNOTTOBEORTOBEORNOT"
print $
undoLZW
['\0' .. '\255']
[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
print $
((==) <*> ((.) <$> undoLZW <*> doLZW) ['\NUL' .. '\255'])
"TOBEORNOTTOBEORTOBEORNOT"

View file

@ -0,0 +1,14 @@
encodeLZW =: 4 : 0
d=. ;/x
r=.0$0
wc=.w=.{.y
for_c. }.y do.
wc=.w,c
if. d e.~ <wc do. w=.wc else.
r=. r, d i.<w
d=.d,<wc
w=.c
end.
end.
r, d i.<w
)

View file

@ -0,0 +1,16 @@
decodeLZW =: 4 : 0
d=.;/x
w=.r=. >d{~{.y
ds=. #d
for_c. }.y do.
select. * c-ds
case. _1 do. r=.r,e=.>c{d
case. 0 do. r=.r,e=.w,{.w
case. do. 'error' return.
end.
d=.d,< w,{.e
w=.e
ds=.ds+1
end.
;r
)

View file

@ -0,0 +1,67 @@
import java.util.*;
public class LZW {
/** Compress a string to a list of output symbols. */
public static List<Integer> compress(String uncompressed) {
// Build the dictionary.
int dictSize = 256;
Map<String,Integer> dictionary = new HashMap<String,Integer>();
for (int i = 0; i < 256; i++)
dictionary.put("" + (char)i, i);
String w = "";
List<Integer> result = new ArrayList<Integer>();
for (char c : uncompressed.toCharArray()) {
String wc = w + c;
if (dictionary.containsKey(wc))
w = wc;
else {
result.add(dictionary.get(w));
// Add wc to the dictionary.
dictionary.put(wc, dictSize++);
w = "" + c;
}
}
// Output the code for w.
if (!w.equals(""))
result.add(dictionary.get(w));
return result;
}
/** Decompress a list of output ks to a string. */
public static String decompress(List<Integer> compressed) {
// Build the dictionary.
int dictSize = 256;
Map<Integer,String> dictionary = new HashMap<Integer,String>();
for (int i = 0; i < 256; i++)
dictionary.put(i, "" + (char)i);
String w = "" + (char)(int)compressed.remove(0);
StringBuffer result = new StringBuffer(w);
for (int k : compressed) {
String entry;
if (dictionary.containsKey(k))
entry = dictionary.get(k);
else if (k == dictSize)
entry = w + w.charAt(0);
else
throw new IllegalArgumentException("Bad compressed k: " + k);
result.append(entry);
// Add w+entry[0] to the dictionary.
dictionary.put(dictSize++, w + entry.charAt(0));
w = entry;
}
return result.toString();
}
public static void main(String[] args) {
List<Integer> compressed = compress("TOBEORNOTTOBEORTOBEORNOT");
System.out.println(compressed);
String decompressed = decompress(compressed);
System.out.println(decompressed);
}
}

View file

@ -0,0 +1,2 @@
[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
TOBEORNOTTOBEORTOBEORNOT

View file

@ -0,0 +1,81 @@
//LZW Compression/Decompression for Strings
var LZW = {
compress: function (uncompressed) {
"use strict";
// Build the dictionary.
var i,
dictionary = {},
c,
wc,
w = "",
result = [],
dictSize = 256;
for (i = 0; i < 256; i += 1) {
dictionary[String.fromCharCode(i)] = i;
}
for (i = 0; i < uncompressed.length; i += 1) {
c = uncompressed.charAt(i);
wc = w + c;
//Do not use dictionary[wc] because javascript arrays
//will return values for array['pop'], array['push'] etc
// if (dictionary[wc]) {
if (dictionary.hasOwnProperty(wc)) {
w = wc;
} else {
result.push(dictionary[w]);
// Add wc to the dictionary.
dictionary[wc] = dictSize++;
w = String(c);
}
}
// Output the code for w.
if (w !== "") {
result.push(dictionary[w]);
}
return result;
},
decompress: function (compressed) {
"use strict";
// Build the dictionary.
var i,
dictionary = [],
w,
result,
k,
entry = "",
dictSize = 256;
for (i = 0; i < 256; i += 1) {
dictionary[i] = String.fromCharCode(i);
}
w = String.fromCharCode(compressed[0]);
result = w;
for (i = 1; i < compressed.length; i += 1) {
k = compressed[i];
if (dictionary[k]) {
entry = dictionary[k];
} else {
if (k === dictSize) {
entry = w + w.charAt(0);
} else {
return null;
}
}
result += entry;
// Add w+entry[0] to the dictionary.
dictionary[dictSize++] = w + entry.charAt(0);
w = entry;
}
return result;
}
}, // For Test Purposes
comp = LZW.compress("TOBEORNOTTOBEORTOBEORNOT"),
decomp = LZW.decompress(comp);
document.write(comp + '<br>' + decomp);

View file

@ -0,0 +1,110 @@
'use strict';
/**
Namespace for LZW compression and decompression.
Methods:
LZW.compress(uncompressed)
LZW.decompress(compressed)
*/
class LZW
{
/**
Perform the LZW compression
uncompressed - String. The string on which to perform the compression.
*/
static compress(uncompressed)
{
// Initialize dictionary
let dictionary = {};
for (let i = 0; i < 256; i++)
{
dictionary[String.fromCharCode(i)] = i;
}
let word = '';
let result = [];
let dictSize = 256;
for (let i = 0, len = uncompressed.length; i < len; i++)
{
let curChar = uncompressed[i];
let joinedWord = word + curChar;
// Do not use dictionary[joinedWord] because javascript objects
// will return values for myObject['toString']
if (dictionary.hasOwnProperty(joinedWord))
{
word = joinedWord;
}
else
{
result.push(dictionary[word]);
// Add wc to the dictionary.
dictionary[joinedWord] = dictSize++;
word = curChar;
}
}
if (word !== '')
{
result.push(dictionary[word]);
}
return result;
}
/**
Decompress LZW array generated by LZW.compress()
compressed - Array. The array that holds LZW compressed data.
*/
static decompress(compressed)
{
// Initialize Dictionary (inverse of compress)
let dictionary = {};
for (let i = 0; i < 256; i++)
{
dictionary[i] = String.fromCharCode(i);
}
let word = String.fromCharCode(compressed[0]);
let result = word;
let entry = '';
let dictSize = 256;
for (let i = 1, len = compressed.length; i < len; i++)
{
let curNumber = compressed[i];
if (dictionary[curNumber] !== undefined)
{
entry = dictionary[curNumber];
}
else
{
if (curNumber === dictSize)
{
entry = word + word[0];
}
else
{
throw 'Error in processing';
return null;
}
}
result += entry;
// Add word + entry[0] to dictionary
dictionary[dictSize++] = word + entry[0];
word = entry;
}
return result;
}
}
let comp = LZW.compress('TOBEORNOTTOBEORTOBEORNOT');
let decomp = LZW.decompress(comp);
console.log(`${comp}
${decomp}`);

View file

@ -0,0 +1,46 @@
# LZW compression/decompression for strings
def lzw_compress:
def decode: [.] | implode;
# Build the dictionary:
256 as $dictSize
| (reduce range(0; $dictSize) as $i ({}; .[ $i | decode ] = $i)) as $dictionary
| reduce explode[] as $i
( [$dictionary, $dictSize, "", []]; # state: [dictionary, dictSize, w, result]
.[0] as $dictionary
| .[1] as $dictSize
| .[2] as $w
| ($i | decode) as $c
| ($w + $c ) as $wc
| if $dictionary[$wc] then .[2] = $wc
else
.[2] = $c # w = c
| .[3] += [$dictionary[$w]] # result += dictionary[w]
| .[0][$wc] = $dictSize # Add wc to the dictionary
| .[1] += 1 # dictSize ++
end
)
# Output the code for w unless w == "":
| if .[2] == "" then .[3]
else .[3] + [.[0][.[2]]]
end
;
def lzw_decompress:
def decode: [.] | implode;
# Build the dictionary - an array of strings
256 as $dictSize
| (reduce range(0; $dictSize) as $i ([]; .[ $i ] = ($i|decode))) as $dictionary
| (.[0]|decode) as $w
| reduce .[1:][] as $k
( [ $dictionary, $dictSize, $w, $w]; # state: [dictionary, dictSize, w, result]
.[0][$k] as $entry
| (if $entry then $entry
elif $k == .[1] then .[2] + .[2][0:1]
else error("lzw_decompress: k=\($k)")
end) as $entry
| .[3] += $entry # result += entry
| .[0][.[1]] = .[2] + $entry[0:1] # dictionary[dictSize] = w + entry.charAt(0);
| .[1] += 1 # dictSize++
| .[2] = $entry # w = entry
) | .[3]
;

View file

@ -0,0 +1 @@
"TOBEORNOTTOBEORTOBEORNOT" | lzw_compress| lzw_decompress

View file

@ -0,0 +1,50 @@
function compressLZW(decompressed::String)
dictsize = 256
dict = Dict{String,Int}(string(Char(i)) => i for i in 0:dictsize)
result = Vector{Int}(undef, 0)
w = ""
for c in decompressed
wc = string(w, c)
if haskey(dict, wc)
w = wc
else
push!(result, dict[w])
dict[wc] = dictsize
dictsize += 1
w = string(c)
end
end
if !isempty(w) push!(result, dict[w]) end
return result
end
function decompressLZW(compressed::Vector{Int})
dictsize = 256
dict = Dict{Int,String}(i => string('\0' + i) for i in 0:dictsize)
result = IOBuffer()
w = string(Char(popfirst!(compressed)))
write(result, w)
for k in compressed
if haskey(dict, k)
entry = dict[k]
elseif k == dictsize
entry = string(w, w[1])
else
error("bad compressed k: $k")
end
write(result, entry)
dict[dictsize] = string(w, entry[1])
dictsize += 1
w = entry
end
return String(take!(result))
end
original = ["0123456789", "TOBEORNOTTOBEORTOBEORNOT", "dudidudidudida"]
compressed = compressLZW.(original)
decompressed = decompressLZW.(compressed)
for (word, comp, decomp) in zip(original, compressed, decompressed)
comprate = (length(word) - length(comp)) / length(word) * 100
println("Original: $word\n-> Compressed: $comp (compr.rate: $(round(comprate, digits=2))%)\n-> Decompressed: $decomp")
end

View file

@ -0,0 +1,62 @@
// version 1.1.2
object Lzw {
/** Compress a string to a list of output symbols. */
fun compress(uncompressed: String): MutableList<Int> {
// Build the dictionary.
var dictSize = 256
val dictionary = mutableMapOf<String, Int>()
(0 until dictSize).forEach { dictionary.put(it.toChar().toString(), it)}
var w = ""
val result = mutableListOf<Int>()
for (c in uncompressed) {
val wc = w + c
if (dictionary.containsKey(wc))
w = wc
else {
result.add(dictionary[w]!!)
// Add wc to the dictionary.
dictionary.put(wc, dictSize++)
w = c.toString()
}
}
// Output the code for w
if (!w.isEmpty()) result.add(dictionary[w]!!)
return result
}
/** Decompress a list of output symbols to a string. */
fun decompress(compressed: MutableList<Int>): String {
// Build the dictionary.
var dictSize = 256
val dictionary = mutableMapOf<Int, String>()
(0 until dictSize).forEach { dictionary.put(it, it.toChar().toString())}
var w = compressed.removeAt(0).toChar().toString()
val result = StringBuilder(w)
for (k in compressed) {
var entry: String
if (dictionary.containsKey(k))
entry = dictionary[k]!!
else if (k == dictSize)
entry = w + w[0]
else
throw IllegalArgumentException("Bad compressed k: $k")
result.append(entry)
// Add w + entry[0] to the dictionary.
dictionary.put(dictSize++, w + entry[0])
w = entry
}
return result.toString()
}
}
fun main(args: Array<String>) {
val compressed = Lzw.compress("TOBEORNOTTOBEORTOBEORNOT")
println(compressed)
val decompressed = Lzw.decompress(compressed)
println(decompressed)
}

View file

@ -0,0 +1,280 @@
DIM LZW(1, 1)
DIM JDlzw(1)
DIM JDch$(1)
LET maxBits = 20 ' maximum bit width of the dictionary: minimum=12; maximum=21
LET resetDictionary = 1 ' flag to reset the dictionary when it gets full: 1=TRUE; 0=FALSE
LET printDictionary = 0 ' output encoding and decoding dictionaries to files
LET maxChunkSize = 2 ^ 14 ' maximum size of the data buffer
LET dSize = 2 ^ maxBits ' maximum dictionary size
LET JDext$ = ".lzw" ' file extension used for created archives
FILEDIALOG "Select a file to test LZW...", "*.*", inputName$
IF inputName$ = "" THEN END
DO ' get fullPath\ and fileName.ext
P = X
X = INSTR(inputName$, "\", (X + 1))
LOOP UNTIL X = 0
filePath$ = LEFT$(inputName$, P)
fileName$ = MID$(inputName$, (P + 1))
DO ' get fileName and .ext
P = X
X = INSTR(fileName$, ".", (X + 1))
LOOP UNTIL X = 0
fileExt$ = MID$(fileName$, P)
fileName$ = LEFT$(fileName$, (P - 1))
GOSUB [lzwEncode]
GOSUB [lzwDecode]
END
''''''''''''''''''''''''''''''''''''''''
' Start LZW Encoder ''''''''''''''''''''
[lzwEncode]
REDIM LZW(dSize, 4)
LET EMPTY=-1:PREFIX=0:BYTE=1:FIRST=2:LESS=3:MORE=4:bmxCorrect=1
LET bitsRemain=0:remainIndex=0:tagCount=0:currentBitSize=8:fileTag$=""
FOR dNext = 0 TO 255 ' initialize dictionary for LZW
' LZW(dNext, PREFIX) = EMPTY ' prefix index of '<index>' <B>
' LZW(dNext, BYTE) = dNext ' byte value of <index> '<B>'
LZW(dNext, FIRST) = EMPTY ' first index to use <index><B> as prefix
' LZW(dNext, LESS) = EMPTY ' lesser index of binary search tree for <B>
' LZW(dNext, MORE) = EMPTY ' greater index of binary search tree for <B>
NEXT dNext
OPEN inputName$ FOR INPUT AS #lzwIN
IF LOF(#lzwIN) < 2 THEN
CLOSE #lzwIN
END
END IF
OPEN fileName$ + fileExt$ + JDext$ FOR OUTPUT AS #lzwOUT
GOSUB [StartFileChunk]
chnkPoint = 1
IF maxBits < 12 THEN maxBits = 12
IF maxBits > 21 THEN maxBits = 21
settings = maxBits - 12 ' setting for dictionary size; 1st decimal +12
IF resetDictionary THEN settings = settings + 100 ' setting for dictionary type; 2nd decimal even=static, odd=adaptive
#lzwOUT, CHR$(settings); ' save settings as 1st byte of output
orgIndex = ASC(LEFT$(fileChunk$, 1)) ' read 1st byte into <index>
WHILE fileChunk$ <> "" ' while the buffer is not empty
DO ' begin the main encoder loop
chnkPoint = chnkPoint + 1
savIndex = FIRST ' initialize the save-to index
prvIndex = orgIndex ' initialize the previous index in search
newByte = ASC(MID$(fileChunk$, chnkPoint, 1)) ' read <B>
dSearch = LZW(orgIndex, FIRST) ' first search index for this <index> in the dictionary
WHILE (dSearch > EMPTY) ' while <index> is present in the dictionary
IF LZW(dSearch, BYTE) = newByte THEN EXIT WHILE ' if <index><B> is found
IF newByte < LZW(dSearch, BYTE) THEN ' else if new <B> is less than <index><B>
savIndex = LESS ' follow lesser binary tree
ELSE
savIndex = MORE ' else follow greater binary tree
END IF
prvIndex = dSearch ' set previous <index>
dSearch = LZW(dSearch, savIndex) ' read next search <index> from binary tree
WEND
IF dSearch = EMPTY THEN ' if <index><B> was not found in the dictionary
GOSUB [WriteIndex] ' write <index> to the output
IF dNext < dSize THEN ' save <index><B> into the dictionary
LZW(prvIndex, savIndex) = dNext
LZW(dNext, PREFIX) = orgIndex
LZW(dNext, BYTE) = newByte
LZW(dNext, FIRST) = EMPTY
LZW(dNext, LESS) = EMPTY
LZW(dNext, MORE) = EMPTY
IF dNext = (2 ^ currentBitSize) THEN currentBitSize = currentBitSize + 1
dNext = dNext + 1
ELSE ' else reset the dictionary... or maybe not
IF resetDictionary THEN
GOSUB [PrintEncode]
REDIM LZW(dSize, 4)
FOR dNext = 0 TO 255
LZW(dNext, FIRST) = EMPTY
NEXT dNext
currentBitSize = 8
bmxCorrect = 0
END IF
END IF
orgIndex = newByte ' set <index> = <B>
ELSE ' if <index><B> was found in the dictionary,
orgIndex = dSearch ' then set <index> = <index><B>
END IF
LOOP WHILE chnkPoint < chunk ' loop until the chunk has been processed
GOSUB [GetFileChunk] ' refill the buffer
WEND ' loop until the buffer is empty
GOSUB [WriteIndex]
IF bitsRemain > 0 THEN #lzwOUT, CHR$(remainIndex);
CLOSE #lzwOUT
CLOSE #lzwIN
IF bmxCorrect THEN ' correct the settings, if needed
IF (currentBitSize < maxBits) OR resetDictionary THEN
IF currentBitSize < 12 THEN currentBitSize = 12
OPEN fileName$ + fileExt$ + JDext$ FOR BINARY AS #lzwOUT
#lzwOUT, CHR$(currentBitSize - 12);
CLOSE #lzwOUT
END IF
END IF
GOSUB [PrintEncode]
REDIM LZW(1, 1)
RETURN
[WriteIndex]
X = orgIndex ' add remaining bits to input
IF bitsRemain > 0 THEN X = remainIndex + (X * (2 ^ bitsRemain))
bitsRemain = bitsRemain + currentBitSize ' add current bit size to output stack
WHILE bitsRemain > 7 ' if 8 or more bits are to be written
#lzwOUT, CHR$(X MOD 256); ' attatch lower 8 bits to output string
X = INT(X / 256) ' shift input value down by 2^8
bitsRemain = bitsRemain - 8 ' adjust counters
WEND
remainIndex = X ' retain trailing bits for next write
RETURN
' End LZW Encoder ''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''
[StartFileChunk]
sizeOfFile = LOF(#lzwIN) ' set EOF marker
bytesRemaining = sizeOfFile ' set EOF counter
chunk = maxChunkSize ' set max buffer size
[GetFileChunk]
fileChunk$ = ""
IF bytesRemaining < 1 THEN RETURN
IF chunk > bytesRemaining THEN chunk = bytesRemaining
bytesRemaining = bytesRemaining - chunk
fileChunk$ = INPUT$(#lzwIN, chunk)
chnkPoint = 0
RETURN
''''''''''''''''''''''''''''''''''''''''
' Start LZW Decoder ''''''''''''''''''''
[lzwDecode]
LET EMPTY=-1:bitsRemain=0:tagCount=0:fileTag$=""
OPEN fileName$ + fileExt$ + JDext$ FOR INPUT AS #lzwIN
OPEN fileName$ + ".Copy" + fileExt$ FOR OUTPUT AS #lzwOUT
GOSUB [StartFileChunk]
chnkPoint = 2
settings = ASC(fileChunk$)
maxBits = VAL(RIGHT$(STR$(settings), 1)) + 12
dSize = 2 ^ maxBits
IF settings > 99 THEN resetDictionary = 1
GOSUB [ResetLZW]
oldIndex = orgIndex
WHILE fileChunk$ <> ""
' decode current index and write to file
GOSUB [GetIndex]
IF JDch$(orgIndex) = "" THEN
tmpIndex = oldIndex
tmp$ = JDch$(tmpIndex)
WHILE JDlzw(tmpIndex) > EMPTY
tmpIndex = JDlzw(tmpIndex)
tmp$ = JDch$(tmpIndex) + tmp$
WEND
tmp$ = tmp$ + LEFT$(tmp$, 1)
ELSE
tmpIndex = orgIndex
tmp$ = JDch$(tmpIndex)
WHILE JDlzw(tmpIndex) > EMPTY
tmpIndex = JDlzw(tmpIndex)
tmp$ = JDch$(tmpIndex) + tmp$
WEND
END IF
#lzwOUT, tmp$;
' add next dictionary entry or reset dictionary
IF dNext < dSize THEN
JDlzw(dNext) = oldIndex
JDch$(dNext) = LEFT$(tmp$, 1)
dNext = dNext + 1
IF dNext = (2 ^ currentBitSize) THEN
IF maxBits > currentBitSize THEN
currentBitSize = currentBitSize + 1
ELSE
IF resetDictionary THEN
GOSUB [PrintDecode]
GOSUB [ResetLZW]
END IF
END IF
END IF
END IF
oldIndex = orgIndex
WEND
CLOSE #lzwOUT
CLOSE #lzwIN
GOSUB [PrintDecode]
REDIM JDlzw(1)
REDIM JDch$(1)
RETURN
[GetIndex]
byteCount = 0:orgIndex = 0
bitsToGrab = currentBitSize - bitsRemain
IF bitsRemain > 0 THEN
orgIndex = lastByte
byteCount = 1
END IF
WHILE bitsToGrab > 0
lastByte = ASC(MID$(fileChunk$, chnkPoint, 1))
orgIndex = orgIndex + (lastByte * (2 ^ (byteCount * 8)))
IF chnkPoint = chunk THEN GOSUB [GetFileChunk]
chnkPoint = chnkPoint + 1
byteCount = byteCount + 1
bitsToGrab = bitsToGrab - 8
WEND
IF bitsRemain > 0 THEN orgIndex = orgIndex / (2 ^ (8 - bitsRemain))
orgIndex = orgIndex AND ((2 ^ currentBitSize) - 1)
bitsRemain = bitsToGrab * (-1)
RETURN
[ResetLZW]
REDIM JDlzw(dSize)
REDIM JDch$(dSize)
FOR dNext = 0 TO 255
JDlzw(dNext) = EMPTY ' Prefix index
JDch$(dNext) = CHR$(dNext) ' New byte value
NEXT dNext
currentBitSize = 8
GOSUB [GetIndex]
#lzwOUT, JDch$(orgIndex);
currentBitSize = 9
RETURN
' End LZW Decoder ''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''
[PrintEncode]
IF printDictionary < 1 THEN RETURN
OPEN "Encode_" + fileTag$ + fileName$ + ".txt" FOR OUTPUT AS #dictOUT
FOR X = 0 TO 255
LZW(X, PREFIX) = EMPTY
LZW(X, BYTE) = X
NEXT X
FOR X = dNext TO 0 STEP -1
tmpIndex = X
tmp$ = CHR$(LZW(tmpIndex, BYTE))
WHILE LZW(tmpIndex, PREFIX) > EMPTY
tmpIndex = LZW(tmpIndex, PREFIX)
tmp$ = CHR$(LZW(tmpIndex, BYTE)) + tmp$
WEND
#dictOUT, X; ":"; tmp$
NEXT X
CLOSE #dictOUT
tagCount = tagCount + 1
fileTag$ = STR$(tagCount) + "_"
RETURN
[PrintDecode]
IF printDictionary < 1 THEN RETURN
OPEN "Decode_" + fileTag$ + fileName$ + ".txt" FOR OUTPUT AS #dictOUT
FOR X = dNext TO 0 STEP -1
tmpIndex = X
tmp$ = JDch$(tmpIndex)
WHILE JDlzw(tmpIndex) > EMPTY
tmpIndex = JDlzw(tmpIndex)
tmp$ = JDch$(tmpIndex) + tmp$
WEND
#dictOUT, X; ":"; tmp$
NEXT X
CLOSE #dictOUT
tagCount = tagCount + 1
fileTag$ = STR$(tagCount) + "_"
RETURN
''''''''''''''''''''''''''''''''''''''''

View file

@ -0,0 +1,50 @@
local function compress(uncompressed) -- string
local dictionary, result, dictSize, w, c = {}, {}, 255, ""
for i = 0, 255 do
dictionary[string.char(i)] = i
end
for i = 1, #uncompressed do
c = string.sub(uncompressed, i, i)
if dictionary[w .. c] then
w = w .. c
else
table.insert(result, dictionary[w])
dictSize = dictSize + 1
dictionary[w .. c] = dictSize
w = c
end
end
if w ~= "" then
table.insert(result, dictionary[w])
end
return result
end
local function decompress(compressed) -- table
local dictionary, dictSize, entry, w, k = {}, 256, "", string.char(compressed[1])
local result = {w}
for i = 0, 255 do
dictionary[i] = string.char(i)
end
for i = 2, #compressed do
k = compressed[i]
if dictionary[k] then
entry = dictionary[k]
elseif k == dictSize then
entry = w .. string.sub(w, 1, 1)
else
return nil, i
end
table.insert(result, entry)
dictionary[dictSize] = w .. string.sub(entry, 1, 1)
dictSize = dictSize + 1
w = entry
end
return table.concat(result)
end
local example = "TOBEORNOTTOBEORTOBEORNOT"
local com = compress(example)
local dec = decompress(com)
print(table.concat(com, ", "))
print(dec)

View file

@ -0,0 +1,52 @@
Module BBCtrans {
\\ LZW compression
plaintext$="TOBEORNOTTOBEORTOBEORNOT"
Function encodeLZW$(i$) {
Def long c, d, i, l, o$, w$
DIM dict$(0 to 4095)
FOR i = 0 TO 255 : dict$(i) = CHR$(i) : NEXT i
l = i
i = 1
w$ = LEFT$(i$,1)
REPEAT{
d = 0
REPEAT {
c = d
IF i > LEN(i$) THEN EXIT
FOR d = 1 TO l-1
IF w$ = dict$(d) THEN EXIT
NEXT d
IF d < l Then i += 1 : w$ += MID$(i$, i, 1)
} UNTIL d >= l
dict$(l) = w$ : l += 1 : w$ = RIGHT$(w$, 1)
o$ += CHR$(c MOD 256) + CHR$(c DIV 256)
} UNTIL i > LEN(i$)
= o$
}
encodeLZW$ = encodeLZW$(plaintext$)
FOR i = 1 TO LEN(encodeLZW$) STEP 2
PRINT ASC(MID$(encodeLZW$,i)) + 256*ASC(MID$(encodeLZW$,i+1));" ";
NEXT i
Print
Function decodeLZW$(i$) {
Def c, i, l, o$, t$, w$
DIM dict$(0 to 4095)
FOR i = 0 TO 255 : dict$(i) = CHR$(i) : NEXT i
l = i
c = ASC(i$) + 256*ASC(MID$(i$,2))
w$ = dict$(c)
o$ = w$
IF LEN(i$) < 4 THEN = o$
FOR i = 3 TO LEN(i$) STEP 2
c = ASC(MID$(i$,i)) + 256*ASC(MID$(i$,i+1))
IF c < l Then { t$ = dict$(c) } ELSE t$ = w$ + LEFT$(w$,1)
o$ += t$
dict$(l) = w$ + LEFT$(t$,1)
l += 1
w$ = t$
NEXT i
= o$
}
Print decodeLZW$(encodeLZW$)
}
BBCtrans

View file

@ -0,0 +1,57 @@
Module FastM2000 {
plaintext$="TOBEORNOTTOBEORTOBEORNOT"
Function encodeLZW$(i$) {
Def long c, d, i, l, o$, w$
Inventory dict
For i = 0 to 255 {Append dict , Chr$(i):=i}
l = i
i = 1
w$ = LEFT$(i$,1)
REPEAT{
d = 0
Repeat {
c = d
IF i > Len(i$) Then Exit
if exist(dict, w$) Then {
d=eval(dict)
} Else Append dict, w$:=l: Exit
if d<l Then i += 1 : w$ += Mid$(i$, i, 1)
} Until d >= l
l += 1 : w$ = Right$(w$, 1)
o$ += Chr$(c Mod 256) + Chr$(c div 256)
} Until i > Len(i$)
= o$
}
encodeLZW$ = encodeLZW$(plaintext$)
Document Doc$
For i = 1 to Len(encodeLZW$) STEP 2
Doc$= Str$(Asc(Mid$(encodeLZW$,i)) + 256*Asc(Mid$(encodeLZW$,i+1)))
Next i
Doc$={
}
Function decodeLZW$(i$) {
Def c, i, l, o$, t$, w$
Inventory Dict
For i = 0 to 255 {Append dict , i:=chr$(i)}
l = i
c = Asc(i$) + 256*Asc(Mid$(i$,2))
w$ = dict$(c)
o$ = w$
IF Len(i$) < 4 Then = o$
For i = 3 to Len(i$) STEP 2 {
c = Asc(Mid$(i$,i)) + 256*Asc(Mid$(i$,i+1))
IF c < l Then {
t$ = dict$(c)
} Else t$ = w$ + LEFT$(w$,1)
o$ += t$
Append dict, l:=w$ + LEFT$(t$,1)
l += 1 : w$ = t$
}
= o$
}
Doc$=decodeLZW$(encodeLZW$)+{
}
Clipboard Doc$
Report Doc$
}
FastM2000

View file

@ -0,0 +1,37 @@
compress[uncompressed_] :=
Module[{dictsize, dictionary, w, result, wc},
dictsize = 256;
dictionary = # -> # & /@ FromCharacterCode /@ Range@dictsize;
w = "";
result = {};
Do[wc = w <> c;
If[MemberQ[dictionary[[All, 1]], wc],
w = wc,
AppendTo[result, w /. dictionary];
AppendTo[dictionary, wc -> dictsize];
dictsize++;
w = c],
{c, Characters[uncompressed]}];
AppendTo[result, w /. dictionary];
result];
decompress::bc = "Bad compressed `1`";
decompress[compressed_] :=
Module[{dictsize, dictionary, w, result, entry},
dictsize = 256;
dictionary = # -> # & /@ FromCharacterCode /@ Range@dictsize;
w = result = compressed[[1]];
Do[Which[MemberQ[dictionary[[All, 1]], k],
entry = k /. dictionary,
k == dictsize,
entry = w <> StringTake[w, 1],
True,
Message[decompress::bc, k]];
result = result <> entry;
AppendTo[dictionary, dictsize -> w <> StringTake[entry, 1]];
dictsize++;
w = entry,
{k, compressed[[2 ;;]]}];
result];
(*How to use:*)
compress["TOBEORNOTTOBEORTOBEORNOT"]
decompress[%]

View file

@ -0,0 +1,53 @@
import tables
proc compress*(uncompressed: string): seq[int] =
# Build the dictionary.
var dictionary: Table[string, int]
for i in 0..255: dictionary[$chr(i)] = i
var w = ""
for c in uncompressed:
var wc = w & c
if wc in dictionary:
w = wc
else:
# Writes "w" to output.
result.add dictionary[w]
# "wc" is a new sequence: add it to the dictionary.
dictionary[wc] = dictionary.len
w = $c
# Write remaining output if necessary.
if w.len > 0: result.add dictionary[w]
proc decompress*(compressed: var seq[int]): string =
# Build the dictionary.
var dictionary: Table[int, string]
for i in 0..255: dictionary[i] = $chr(i)
var w = dictionary[compressed[0]]
compressed.delete(0)
result = w
for k in compressed:
var entry: string
if k in dictionary:
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.
dictionary[dictionary.len] = w & entry[0]
w = entry
when isMainModule:
var compressed = compress("TOBEORNOTTOBEORTOBEORNOT")
echo compressed
var decompressed = decompress(compressed)
echo decompressed

View file

@ -0,0 +1,80 @@
#directory "+extlib" (* or maybe "+site-lib/extlib/" *)
#load "extLib.cma"
open ExtString
(** compress a string to a list of output symbols *)
let compress ~uncompressed =
(* build the dictionary *)
let dict_size = 256 in
let dictionary = Hashtbl.create 397 in
for i=0 to 255 do
let str = String.make 1 (char_of_int i) in
Hashtbl.add dictionary str i
done;
let f = (fun (w, dict_size, result) c ->
let c = String.make 1 c in
let wc = w ^ c in
if Hashtbl.mem dictionary wc then
(wc, dict_size, result)
else
begin
(* add wc to the dictionary *)
Hashtbl.add dictionary wc dict_size;
let this = Hashtbl.find dictionary w in
(c, dict_size + 1, this::result)
end
) in
let w, _, result =
String.fold_left f ("", dict_size, []) uncompressed
in
(* output the code for w *)
let result =
if w = ""
then result
else (Hashtbl.find dictionary w) :: result
in
(List.rev result)
;;
exception ValueError of string
(** decompress a list of output symbols to a string *)
let decompress ~compressed =
(* build the dictionary *)
let dict_size = 256 in
let dictionary = Hashtbl.create 397 in
for i=0 to pred dict_size do
let str = String.make 1 (char_of_int i) in
Hashtbl.add dictionary i str
done;
let w, compressed =
match compressed with
| hd::tl -> (String.make 1 (char_of_int hd)), tl
| [] -> failwith "empty input"
in
let result = [w] in
let result, _, _ =
List.fold_left (fun (result, w, dict_size) k ->
let entry =
if Hashtbl.mem dictionary k then
Hashtbl.find dictionary k
else if k = Hashtbl.length dictionary then
w ^ (String.make 1 w.[0])
else
raise(ValueError(Printf.sprintf "Bad compressed k: %d" k))
in
let result = entry :: result in
(* add (w ^ entry.[0]) to the dictionary *)
Hashtbl.add dictionary dict_size (w ^ (String.make 1 entry.[0]));
(result, entry, dict_size + 1)
) (result, w, dict_size) compressed
in
(List.rev result)
;;

View file

@ -0,0 +1,2 @@
val compress : uncompressed:string -> int list
val decompress : compressed:int list -> string list

View file

@ -0,0 +1,39 @@
let greatest = List.fold_left max 0 ;;
(** number of bits needed to encode the integer m *)
let n_bits m =
let m = float m in
let rec aux n =
let max = (2. ** n) -. 1. in
if max >= m then int_of_float n
else aux (n +. 1.0)
in
aux 1.0
;;
let write_compressed ~filename ~compressed =
let nbits = n_bits(greatest compressed) in
let oc = open_out filename in
output_byte oc nbits;
let ob = IO.output_bits(IO.output_channel oc) in
List.iter (IO.write_bits ob nbits) compressed;
IO.flush_bits ob;
close_out oc;
;;
let read_compressed ~filename =
let ic = open_in filename in
let nbits = input_byte ic in
let ib = IO.input_bits(IO.input_channel ic) in
let rec loop acc =
try
let code = IO.read_bits ib nbits in
loop (code::acc)
with _ -> List.rev acc
in
let compressed = loop [] in
let result = decompress ~compressed in
let buf = Buffer.create 2048 in
List.iter (Buffer.add_string buf) result;
(Buffer.contents buf)
;;

View file

@ -0,0 +1,104 @@
use Collection;
class LZW {
function : Main(args : String[]) ~ Nil {
compressed := Compress("TOBEORNOTTOBEORTOBEORNOT");
Show(compressed);
decompressed := Decompress(compressed);
decompressed->PrintLine();
}
function : native : Compress(uncompressed : String) ~ IntVector {
# Build the dictionary.
dictSize := 256;
dictionary := StringMap->New();
for (i := 0; i < 256; i+=1;) {
key := "";
key->Append(i->As(Char));
dictionary->Insert(key, IntHolder->New(i));
};
w := "";
result := IntVector->New();
each (i : uncompressed) {
c := uncompressed->Get(i);
wc := String->New(w);
wc->Append(c);
if (dictionary->Has(wc)) {
w := wc;
}
else {
value := dictionary->Find(w)->As(IntHolder);
result->AddBack(value->Get());
# Add wc to the dictionary.
dictionary->Insert(wc, IntHolder->New(dictSize));
dictSize+=1;
w := "";
w->Append(c);
};
};
# Output the code for w.
if (w->Size() > 0) {
value := dictionary->Find(w)->As(IntHolder);
result->AddBack(value->Get());
};
return result;
}
function : Decompress(compressed : IntVector) ~ String {
# Build the dictionary.
dictSize := 256;
dictionary := IntMap->New();
for (i := 0; i < 256; i+=1;) {
value := "";
value->Append(i->As(Char));
dictionary->Insert(i, value);
};
w := "";
found := compressed->Remove(0);
w->Append(found->As(Char));
result := String->New(w);
each (i : compressed) {
k := compressed->Get(i);
entry : String;
if (dictionary->Has(k)) {
entry := dictionary->Find(k);
}
else if (k = dictSize) {
entry := String->New(w);
entry->Append(w->Get(0));
}
else {
return "";
};
result->Append(entry);
# Add w+entry[0] to the dictionary.
value := String->New(w);
value->Append(entry->Get(0));
dictionary->Insert(dictSize, value);
dictSize+=1;
w := entry;
};
return result;
}
function : Show(results : IntVector) ~ Nil {
"["->Print();
each(i : results) {
results->Get(i)->Print();
if(i + 1 < results->Size()) {
", "->Print();
};
};
"]"->PrintLine();
}
}

View file

@ -0,0 +1,86 @@
#import <Foundation/Foundation.h>
#import <stdio.h>
@interface LZWCompressor : NSObject
{
@private
NSMutableArray *iostream;
NSMutableDictionary *dict;
NSUInteger codemark;
}
-(instancetype) init;
-(instancetype) initWithArray: (NSMutableArray *) stream;
-(BOOL) compressData: (NSData *) string;
-(void) setArray: (NSMutableArray *) stream;
-(NSArray *) getArray;
@end
@implementation LZWCompressor : NSObject
-(instancetype) init
{
self = [super init];
if ( self )
{
iostream = nil;
codemark = 256;
dict = [[NSMutableDictionary alloc] initWithCapacity: 512];
}
return self;
}
-(instancetype) initWithArray: (NSMutableArray *) stream
{
self = [self init];
if ( self )
{
[self setArray: stream];
}
return self;
}
-(void) setArray: (NSMutableArray *) stream
{
iostream = stream;
}
-(BOOL) compressData: (NSData *) string;
{
// prepare dict
for(NSUInteger i=0; i < 256; i++)
{
unsigned char j = i;
NSData *s = [NSData dataWithBytes: &j length: 1];
dict[s] = @(i);
}
NSData *w = [NSData data];
for(NSUInteger i=0; i < [string length]; i++)
{
NSMutableData *wc = [NSMutableData dataWithData: w];
[wc appendData: [string subdataWithRange: NSMakeRange(i, 1)]];
if ( dict[wc] != nil )
{
w = wc;
} else {
[iostream addObject: dict[w]];
dict[wc] = @(codemark);
codemark++;
w = [string subdataWithRange: NSMakeRange(i, 1)];
}
}
if ( [w length] != 0 )
{
[iostream addObject: dict[w]];
}
return YES;
}
-(NSArray *) getArray
{
return iostream;
}
@end

View file

@ -0,0 +1,21 @@
NSString *text = @"TOBEORNOTTOBEORTOBEORNOT";
int main()
{
@autoreleasepool {
NSMutableArray *array = [[NSMutableArray alloc] init];
LZWCompressor *lzw = [[LZWCompressor alloc]
initWithArray: array ];
if ( lzw )
{
[lzw compressData: [text dataUsingEncoding: NSUTF8StringEncoding]];
for ( id obj in array )
{
printf("%u\n", [obj unsignedIntValue]);
}
}
}
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,25 @@
(define (compress str)
(let loop ((dc (fold (lambda (f x) ; dictionary (simplest, not optimized), with reversed codes
(cons (list x) (cons x f)))
'() (iota 256)))
(w '()) ; output sequence (reversed)
(s 256) ; maximal dictionary code value + 1
(x '()) ; current sequence
(r (str-iter str))); input stream
(cond
((null? r)
(reverse (cons (cadr (member x dc)) w)))
((pair? r)
(let ((xy (cons (car r) x)))
(if (member xy dc)
(loop dc w s xy (cdr r))
(loop (cons xy (cons s dc)) ; update dictionary with xy . s
(cons (cadr (member x dc)) w) ; add code to output stream
(+ s 1) ; increase code
(list (car r)) ; new current sequence
(cdr r))))) ; next input
(else
(loop dc w s x (r)))))
)
(print (compress "TOBEORNOTTOBEORTOBEORNOT")) ; => (84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263)

View file

@ -0,0 +1,27 @@
(define (decompress str)
(let loop ((dc (fold (lambda (f x) ; dictionary (simplest, not optimized), with reversed codes
(cons x (cons (list x) f)))
'() (iota 256)))
(w '()) ; output sequence (reversed)
(s 256) ; maximal dictionary code value + 1
(x '()) ; current symbols sequence
(r (str-iter str))); input stream
(cond
((null? r)
(reverse w))
((pair? r)
(let*((y (cadr (member (car r) dc)))
(xy (append y x)))
(if (member xy dc)
(loop dc (append y w) s xy (cdr r)) ; вряд ли такое будет...
(loop (cons s (cons xy dc)) ; update dictionary with xy . s
(append y w) ; add phrase to output stream
(+ s 1)
y ; new initial code
(cdr r))))) ; next input
(else
(loop dc w s x (r))))))
(print (runes->string
(decompress (runes->string '(84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263)))))
; => TOBEORNOTTOBEORTOBEEORNOT

View file

@ -0,0 +1,64 @@
class LZW
{
function compress($unc) {
$i;$c;$wc;
$w = "";
$dictionary = array();
$result = array();
$dictSize = 256;
for ($i = 0; $i < 256; $i += 1) {
$dictionary[chr($i)] = $i;
}
for ($i = 0; $i < strlen($unc); $i++) {
$c = $unc[$i];
$wc = $w.$c;
if (array_key_exists($w.$c, $dictionary)) {
$w = $w.$c;
} else {
array_push($result,$dictionary[$w]);
$dictionary[$wc] = $dictSize++;
$w = (string)$c;
}
}
if ($w !== "") {
array_push($result,$dictionary[$w]);
}
return implode(",",$result);
}
function decompress($com) {
$com = explode(",",$com);
$i;$w;$k;$result;
$dictionary = array();
$entry = "";
$dictSize = 256;
for ($i = 0; $i < 256; $i++) {
$dictionary[$i] = chr($i);
}
$w = chr($com[0]);
$result = $w;
for ($i = 1; $i < count($com);$i++) {
$k = $com[$i];
if (isset($dictionary[$k])) {
$entry = $dictionary[$k];
} else {
if ($k === $dictSize) {
$entry = $w.$w[0];
} else {
return null;
}
}
$result .= $entry;
$dictionary[$dictSize++] = $w . $entry[0];
$w = $entry;
}
return $result;
}
}
//How to use
$str = 'TOBEORNOTTOBEORTOBEORNOT';
$lzw = new LZW();
$com = $lzw->compress($str);
$dec = $lzw->decompress($com);
echo $com . "<br>" . $dec;

View file

@ -0,0 +1,150 @@
*process source xref attributes or(!);
lzwt: Proc Options(main);
Dcl (LEFT,LENGTH,SUBSTR,TRANSLATE,TRIM,UNSPEC) Builtin;
Dcl SYSPRINT Print;
Dcl str Char(50) Var Init('TOBEORNOTTOBEORTOBEORNOT');
Dcl compressed Char(80) Var;
Dcl decompressed Char(80) Var;
Dcl 1 dict(0:300),
2 key Char(5) Var,
2 inx Bin Fixed(16) Unsigned;
Dcl dict_size Bin Fixed(31) Init(256);
Dcl hi Bin Fixed(16) Unsigned Init(65535);
Put Edit('str=',str)(Skip,a,a);
compressed = compress(str);
Put Edit(compressed)(Skip,a);
decompressed = decompress(compressed);
Put Edit('dec=',decompressed)(Skip,a,a);
If decompressed=str Then
Put Edit('decompression ok')(Skip,a);
Else
Put Edit('decompression not ok')(Skip,a);
compress: Proc(s) Returns(Char(80) Var);
Dcl s Char(*) Var;
Dcl res Char(80) Var;
Dcl i Bin Fixed(31);
Dcl c Char(1);
Dcl w Char(5) Var;
Dcl wc Char(5) Var;
dict.key='';
Dcl ii Bin Fixed(8) Unsigned;
Do i=0 To 255;
ii=i;
Unspec(c)=unspec(ii);
dict.key(i)=c;
dict.inx(i)=i;
End;
res='[';
w='';
Do i=1 To length(s);
c=substr(s,i,1);
wc=w!!c;
If dicti(wc)^=hi Then Do;
w=wc;
End;
Else Do;
res=res!!trim(dicti(w))!!', ';
Call dict_add(wc,dict_size);
w=c;
End;
End;
If w^='' Then
res=res!!trim(dicti(w))!!', ';
substr(res,length(res)-1,1)=']';
Return(res);
dicti: Proc(needle) Returns(Bin Fixed(31));
Dcl needle Char(*) Var;
Dcl i Bin Fixed(31);
Do i=1 To dict_size;
If dict.key(i)=needle Then
Return(i);
End;
Return(hi);
End;
dict_add: Proc(needle,dict_size);
Dcl needle Char(*) Var;
Dcl dict_size Bin Fixed(31);
dict.key(dict_size)=needle;
dict.inx(dict_size)=dict_size;
dict_size+=1;
End;
End;
decompress: Proc(s) Returns(Char(80) Var);
Dcl s Char(80) Var;
Dcl ss Char(80) Var;
Dcl words(50) Char(5) Var;
Dcl wn Bin Fixed(31);
Dcl ww Bin Fixed(31);
Dcl c Char(1);
Dcl entry Char(5) Var;
Dcl w Char(5) Var;
Dcl res Char(80) Var;
ss=translate(s,' ','[],');
Call mk_words(ss,words,wn);
dict.key='';
dict.inx=hi;
Dcl i Bin Fixed(31);
Dcl ii Bin Fixed(8) Unsigned;
Dcl dict(0:300) Char(5) Var;
Dcl dict_size Bin Fixed(31);
Do i=0 To 255;
ii=i;
Unspec(c)=unspec(ii);
dict(i)=c;
End;
dict_size=256;
ww=words(1);
w=dict(ww);
res=w;
Do i=2 To wn;
ww=words(i);
Select;
When(dict(ww)^='')
entry=dict(ww);
When(ww=dict_size)
entry=w!!substr(w,1,1);
Otherwise
Put Edit('Bad compressed k: ',ww)(Skip,a,a);
End;
res=res!!entry;
dict(dict_size)=w!!substr(entry,1,1);
dict_size+=1;
w=entry;
End;
Return(res);
End;
mk_words: Proc(st,arr,arrn);
Dcl st Char(*) Var;
Dcl sv Char(80) Var;
Dcl arr(*) Char(5) Var;
Dcl arrn Bin fixed(31);
Dcl elem Char(5) Var;
arrn=0;
sv=st!!' ';
elem='';
Do While(length(sv)>0);
If left(sv,1)=' ' Then Do;
If elem>'' Then Do;
arrn+=1;
arr(arrn)=elem;
elem='';
End;
End;
Else
elem=elem!!left(sv,1);
sv=substr(sv,2);
End;
End;
Return;
End;

View file

@ -0,0 +1,65 @@
# Compress a string to a list of output symbols.
sub compress {
my $uncompressed = shift;
# Build the dictionary.
my $dict_size = 256;
my %dictionary = map {chr $_ => chr $_} 0..$dict_size-1;
my $w = "";
my @result;
foreach my $c (split '', $uncompressed) {
my $wc = $w . $c;
if (exists $dictionary{$wc}) {
$w = $wc;
} else {
push @result, $dictionary{$w};
# Add wc to the dictionary.
$dictionary{$wc} = $dict_size;
$dict_size++;
$w = $c;
}
}
# Output the code for w.
if ($w) {
push @result, $dictionary{$w};
}
return @result;
}
# Decompress a list of output ks to a string.
sub decompress {
my @compressed = @_;
# Build the dictionary.
my $dict_size = 256;
my %dictionary = map {chr $_ => chr $_} 0..$dict_size-1;
my $w = shift @compressed;
my $result = $w;
foreach my $k (@compressed) {
my $entry;
if (exists $dictionary{$k}) {
$entry = $dictionary{$k};
} elsif ($k == $dict_size) {
$entry = $w . substr($w,0,1);
} else {
die "Bad compressed k: $k";
}
$result .= $entry;
# Add w+entry[0] to the dictionary.
$dictionary{$dict_size} = $w . substr($entry,0,1);
$dict_size++;
$w = $entry;
}
return $result;
}
# How to use:
my @compressed = compress('TOBEORNOTTOBEORTOBEORNOT');
print "@compressed\n";
my $decompressed = decompress(@compressed);
print "$decompressed\n";

View file

@ -0,0 +1,59 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<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>
<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>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<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>
<span style="color: #004080;">string</span> <span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<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>
<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>
<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>
<span style="color: #000000;">word</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">c</span>
<span style="color: #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>
<span style="color: #000000;">dictSize</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">destroy_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<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>
<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>
<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>
<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>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<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>
<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>
<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>
<span style="color: #008080;">if</span> <span style="color: #000000;">ki</span> <span style="color: #008080;">then</span>
<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>
<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>
<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>
<span style="color: #008080;">else</span>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">dent</span>
<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>
<span style="color: #000000;">dictSize</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dent</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">destroy_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">example</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"TOBEORNOTTOBEORTOBEORNOT"</span>
<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>
<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>
<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>
<!--

View file

@ -0,0 +1,85 @@
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].

View file

@ -0,0 +1,31 @@
(de lzwCompress (Lst)
(let (Codes 255 Dict)
(balance 'Dict
(make
(for C Codes
(link (cons (char C) C)) ) ) )
(make
(let W (pop 'Lst)
(for C Lst
(let WC (pack W C)
(if (lup Dict WC)
(setq W WC)
(link (cdr (lup Dict W)))
(idx 'Dict (cons WC (inc 'Codes)) T)
(setq W C) ) ) )
(and W (link (cdr (lup Dict W)))) ) ) ) )
(de lzwDecompress (Lst)
(let (Codes 255 Dict)
(balance 'Dict
(make
(for C Codes
(link (list C (char C))) ) ) )
(make
(let W NIL
(for N Lst
(let WC (if (lup Dict N) (cdr @) (cons (last W) W))
(chain (reverse WC))
(when W
(idx 'Dict (cons (inc 'Codes) (cons (last WC) W)) T) )
(setq W WC) ) ) ) ) ) )

View file

@ -0,0 +1,97 @@
Procedure compress(uncompressed.s, List result.u())
;Compress a string to a list of output symbols
;Build the dictionary.
Protected dict_size = 255, i
newmap dict.u()
For i = 0 To 254
dict(Chr(i + 1)) = i
Next
Protected w.s, wc.s, *c.Character = @uncompressed
w = ""
LastElement(result())
While *c\c <> #Null
wc = w + Chr(*c\c)
If FindMapElement(dict(), wc)
w = wc
Else
AddElement(result())
result() = dict(w)
;Add wc to the dictionary
dict(wc) = dict_size
dict_size + 1 ;no check is performed for overfilling the dictionary.
w = Chr(*c\c)
EndIf
*c + 1
Wend
;Output the code for w
If w
AddElement(result())
result() = dict(w)
EndIf
EndProcedure
Procedure.s decompress(List compressed.u())
;Decompress a list of encoded values to a string
If ListSize(compressed()) = 0: ProcedureReturn "": EndIf
;Build the dictionary.
Protected dict_size = 255, i
Dim dict.s(255)
For i = 1 To 255
dict(i - 1) = Chr(i)
Next
Protected w.s, entry.s, result.s
FirstElement(compressed())
w = dict(compressed())
result = w
i = 0
While NextElement(compressed())
i + 1
If compressed() < dict_size
entry = dict(compressed())
ElseIf i = dict_size
entry = w + Left(w, 1)
Else
MessageRequester("Error","Bad compression at [" + Str(i) + "]")
ProcedureReturn result;abort
EndIf
result + entry
;Add w + Left(entry, 1) to the dictionary
If ArraySize(dict()) <= dict_size
Redim dict(dict_size + 256)
EndIf
dict(dict_size) = w + Left(entry, 1)
dict_size + 1 ;no check is performed for overfilling the dictionary.
w = entry
Wend
ProcedureReturn result
EndProcedure
If OpenConsole()
;How to use:
Define initial.s, decompressed.s
Print("Type something: ")
initial = Input()
NewList compressed.u()
compress(initial, compressed())
ForEach compressed()
Print(Str(compressed()) + " ")
Next
PrintN("")
decompressed = decompress(compressed())
PrintN(decompressed)
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf

View file

@ -0,0 +1,63 @@
def compress(uncompressed):
"""Compress a string to a list of output symbols."""
# Build the dictionary.
dict_size = 256
dictionary = dict((chr(i), i) for i in range(dict_size))
# in Python 3: dictionary = {chr(i): i for i in range(dict_size)}
w = ""
result = []
for c in uncompressed:
wc = w + c
if wc in dictionary:
w = wc
else:
result.append(dictionary[w])
# Add wc to the dictionary.
dictionary[wc] = dict_size
dict_size += 1
w = c
# Output the code for w.
if w:
result.append(dictionary[w])
return result
def decompress(compressed):
"""Decompress a list of output ks to a string."""
from io import StringIO
# Build the dictionary.
dict_size = 256
dictionary = dict((i, chr(i)) for i in range(dict_size))
# in Python 3: dictionary = {i: chr(i) for i in range(dict_size)}
# use StringIO, otherwise this becomes O(N^2)
# due to string concatenation in a loop
result = StringIO()
w = chr(compressed.pop(0))
result.write(w)
for k in compressed:
if k in dictionary:
entry = dictionary[k]
elif k == dict_size:
entry = w + w[0]
else:
raise ValueError('Bad compressed k: %s' % k)
result.write(entry)
# Add w+entry[0] to the dictionary.
dictionary[dict_size] = w + entry[0]
dict_size += 1
w = entry
return result.getvalue()
# How to use:
compressed = compress('TOBEORNOTTOBEORTOBEORNOT')
print (compressed)
decompressed = decompress(compressed)
print (decompressed)

View file

@ -0,0 +1,76 @@
/* REXX ---------------------------------------------------------------
* 20.07.2014 Walter Pachl translated from Java
* 21.07.2014 WP allow for blanks in the string
*--------------------------------------------------------------------*/
Parse Arg str
default="TOBEORNOTTOBEORTOBEORNOT"
If str='' Then
str=default
/* str=space(str,0) */
Say 'str='str
compressed = compress(str)
Say compressed
If str=default Then Do
cx='[84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]'
If cx==compressed Then Say 'compression ok'
End
decompressed = decompress(compressed)
Say 'dec='decompressed
If decompressed=str Then Say 'decompression ok'
Exit
compress: Procedure
Parse Arg uncompressed
dict.=''
Do i=0 To 255
z=d2c(i)
d.i=z
dict.z=i
End
dict_size=256
res='['
w=''
Do i=1 To length(uncompressed)
c=substr(uncompressed,i,1)
wc=w||c
If dict.wc<>'' Then
w=wc
Else Do
res=res||dict.w', '
dict.wc=dict_size
dict_size=dict_size+1
w=c
End
End
If w<>'' Then
res=res||dict.w', '
Return left(res,length(res)-2)']'
decompress: Procedure
Parse Arg compressed
compressed=space(translate(compressed,'','[],'))
d.=''
Do i=0 To 255
z=d2c(i)
d.i=z
End
dict_size=256
Parse Var compressed w compressed
res=d.w
w=d.w
Do i=1 To words(compressed)
k=word(compressed,i)
Select
When d.k<>'' | d.k==' ' then /* allow for blank */
entry=d.k
When k=dict_size Then
entry=w||substr(w,1,1)
Otherwise
Say "Bad compressed k: " k
End
res=res||entry
d.dict_size=w||substr(entry,1,1)
dict_size=dict_size+1
w=entry
End
Return res

View file

@ -0,0 +1,24 @@
/*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 text; if text='' then text= $$$ /*get an optional argument from the CL.*/
say 'original text=' text /* [↑] Not specified? Then use default*/
cypher= LZWc(text) /*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. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
LZWi: arg i,@.; #=256; do j=0 for #; _=d2c(j); if i then @.j=_; else @._=j; end; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
LZWc: procedure; parse arg y,,$; call LZWi 0; w= /*LZW compress.*/
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. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
LZWd: procedure; parse arg x y; call LZWi 1; $= @.x; w= $ /*LZW decompress.*/
do k=1 for words(y); z= word(y, k)
if @.z\=='' | @.k==" " then ?= @.z
else if z==# then ?= w || left(w, 1)
$= $ || ?
@.#= w || left(?, 1); w= ?; #= # + 1 /*bump dict. size*/
end /*k*/; return $

View file

@ -0,0 +1,57 @@
#lang racket
; utilities
(define-syntax def (make-rename-transformer #'define))
(define (dict-ref d w) (hash-ref d w #f))
(define (append-char w c) (string-append w (string c)))
(define (append-first w s) (append-char w (string-ref s 0)))
;; Compress a string with LZW
(define (compress uncompressed)
(def d (make-hash))
(def (dict-add d w) (hash-set! d w (hash-count d)))
; build initial dictionary
(for ([i (in-range 256)])
(def s (string (integer->char i)))
(hash-set! d s s))
; compress the string
(def result '())
(def (emit! i) (set! result (cons i result)))
(def w "")
(for ([c uncompressed])
(define wc (append-char w c))
(cond
[(dict-ref d wc) (set! w wc)]
[else (emit! (dict-ref d w))
(dict-add d wc)
(set! w (string c))]))
(emit! (dict-ref d w))
(reverse result))
;; Decompress a LZW compressed string
(define (decompress compressed)
(def d (make-hash))
(def (dict-add! w) (hash-set! d (hash-count d) w))
; build initial dictionary
(for ([i (in-range 256)])
(def s (string (integer->char i)))
(hash-set! d s s))
; decompress the list
(def w (first compressed))
(apply string-append
w
(for/list ([k (rest compressed)])
(def entry
(or (dict-ref d k)
(if (eqv? k (hash-count d))
(append-first w w)
(error 'lzq-decompress "faulty input"))))
(dict-add! (append-first w entry))
(set! w entry)
entry)))
(def uncompressed "TOBEORNOTTOBEORTOBEORNOT")
(displayln uncompressed)
(def compressed (compress uncompressed))
(displayln compressed)
(def decompressed (decompress compressed))
(displayln decompressed)

View file

@ -0,0 +1,46 @@
# 20200421 Updated Raku programming solution ; add unicode support
sub compress(Str $uncompressed --> Seq) {
my $dict-size = 256;
my %dictionary = (.chr => .chr for ^$dict-size);
my $w = "";
gather {
for $uncompressed.encode('utf8').list.chrs.comb -> $c {
my $wc = $w ~ $c;
if %dictionary{$wc}:exists { $w = $wc }
else {
take %dictionary{$w};
%dictionary{$wc} = +%dictionary;
$w = $c;
}
}
take %dictionary{$w} if $w.chars;
}
}
sub decompress(@compressed --> Str) {
my $dict-size = 256;
my %dictionary = (.chr => .chr for ^$dict-size);
my $w = shift @compressed;
( Blob.new: flat ( gather {
take $w;
for @compressed -> $k {
my $entry;
if %dictionary{$k}:exists { take $entry = %dictionary{$k} }
elsif $k == $dict-size { take $entry = $w ~ $w.substr(0,1) }
else { die "Bad compressed k: $k" }
%dictionary{$dict-size++} = $w ~ $entry.substr(0,1);
$w = $entry;
}
} )».ords ).decode('utf-8')
}
say my @compressed = compress('TOBEORNOTTOBEORTOBEORNOT');
say decompress(@compressed);
@compressed = compress('𝒳𝒴𝒵𝒳𝒴𝒵𝒳𝒴𝒵');
say decompress(@compressed);

View file

@ -0,0 +1,78 @@
# Project : LZW compression
plaintext = "TOBEORNOTTOBEORTOBEORNOT"
result = []
encode = encodelzw(plaintext)
for i = 1 to len(encode) step 2
add(result,ascii(substr(encode,i,1)) + 256*ascii(substr(encode,i+1,1)))
next
showarray(result)
see decodelzw(encode)
func encodelzw(text)
o = ""
dict = list(4096)
for i = 1 to 255
dict[i] = char(i)
next
l = i
i = 1
w = left(text,1)
while i < len(text)
d = 0
while d < l
c = d
if i > len(text)
exit
ok
for d = 1 to l
if w = dict[d]
exit
ok
next
if d < l
i = i + 1
w = w + substr(text,i,1)
ok
end
dict[l] = w
l = l + 1
w = right(w,1)
o = o + char(c % 256) + char(floor(c / 256))
end
return o
func decodelzw(text)
o = ""
dict = list(4096)
for i = 1 to 255
dict[i] = char(i)
next
l = i
c = ascii(left(text,1)) + 256*ascii(substr(text,2,1))
w = dict[c]
o = w
if len(text) < 4
return o
ok
for i = 3 to len(text) step 2
c = ascii(substr(text,i,1)) + 256*ascii(substr(text,i+1,1))
if c < l
t = dict[c]
else
t = w + left(w,1)
ok
o = o + t
dict[l] = w + left(t,1)
l = l + 1
w = t
next
return o
func showarray(vect)
svect = ""
for n = 1 to len(vect)
svect = svect + vect[n] + " "
next
svect = left(svect, len(svect) - 1)
see svect + nl

View file

@ -0,0 +1,57 @@
# Compress a string to a list of output symbols.
def compress(uncompressed)
# Build the dictionary.
dict_size = 256
dictionary = Hash[ Array.new(dict_size) {|i| [i.chr, i.chr]} ]
w = ""
result = []
for c in uncompressed.split('')
wc = w + c
if dictionary.has_key?(wc)
w = wc
else
result << dictionary[w]
# Add wc to the dictionary.
dictionary[wc] = dict_size
dict_size += 1
w = c
end
end
# Output the code for w.
result << dictionary[w] unless w.empty?
result
end
# Decompress a list of output ks to a string.
def decompress(compressed)
# Build the dictionary.
dict_size = 256
dictionary = Hash[ Array.new(dict_size) {|i| [i.chr, i.chr]} ]
w = result = compressed.shift
for k in compressed
if dictionary.has_key?(k)
entry = dictionary[k]
elsif k == dict_size
entry = w + w[0,1]
else
raise 'Bad compressed k: %s' % k
end
result += entry
# Add w+entry[0] to the dictionary.
dictionary[dict_size] = w + entry[0,1]
dict_size += 1
w = entry
end
result
end
# How to use:
compressed = compress('TOBEORNOTTOBEORTOBEORNOT')
p compressed
decompressed = decompress(compressed)
puts decompressed

View file

@ -0,0 +1,77 @@
use std::collections::HashMap;
fn compress(data: &[u8]) -> Vec<u32> {
// Build initial dictionary.
let mut dictionary: HashMap<Vec<u8>, u32> = (0u32..=255)
.map(|i| (vec![i as u8], i))
.collect();
let mut w = Vec::new();
let mut compressed = Vec::new();
for &b in data {
let mut wc = w.clone();
wc.push(b);
if dictionary.contains_key(&wc) {
w = wc;
} else {
// Write w to output.
compressed.push(dictionary[&w]);
// wc is a new sequence; add it to the dictionary.
dictionary.insert(wc, dictionary.len() as u32);
w.clear();
w.push(b);
}
}
// Write remaining output if necessary.
if !w.is_empty() {
compressed.push(dictionary[&w]);
}
compressed
}
fn decompress(mut data: &[u32]) -> Vec<u8> {
// Build the dictionary.
let mut dictionary: HashMap::<u32, Vec<u8>> = (0u32..=255)
.map(|i| (i, vec![i as u8]))
.collect();
let mut w = dictionary[&data[0]].clone();
data = &data[1..];
let mut decompressed = w.clone();
for &k in data {
let entry = if dictionary.contains_key(&k) {
dictionary[&k].clone()
} else if k == dictionary.len() as u32 {
let mut entry = w.clone();
entry.push(w[0]);
entry
} else {
panic!("Invalid dictionary!");
};
decompressed.extend_from_slice(&entry);
// New sequence; add it to the dictionary.
w.push(entry[0]);
dictionary.insert(dictionary.len() as u32, w);
w = entry;
}
decompressed
}
fn main() {
let compressed = compress("TOBEORNOTTOBEORTOBEORNOT".as_bytes());
println!("{:?}", compressed);
let decompressed = decompress(&compressed);
let decompressed = String::from_utf8(decompressed).unwrap();
println!("{}", decompressed);
}

View file

@ -0,0 +1,45 @@
def compress(tc:String) = {
//initial dictionary
val startDict = (1 to 255).map(a=>(""+a.toChar,a)).toMap
val (fullDict, result, remain) = tc.foldLeft ((startDict, List[Int](), "")) {
case ((dict,res,leftOver),nextChar) =>
if (dict.contains(leftOver + nextChar)) // current substring already in dict
(dict, res, leftOver+nextChar)
else if (dict.size < 4096) // add to dictionary
(dict + ((leftOver+nextChar, dict.size+1)), dict(leftOver) :: res, ""+nextChar)
else // dictionary is full
(dict, dict(leftOver) :: res, ""+nextChar)
}
if (remain.isEmpty) result.reverse else (fullDict(remain) :: result).reverse
}
def decompress(ns: List[Int]): String = {
val startDict = (1 to 255).map(a=>(a,""+a.toChar)).toMap
val (_, result, _) =
ns.foldLeft[(Map[Int, String], List[String], Option[(Int, String)])]((startDict, Nil, None)) {
case ((dict, result, conjecture), n) => {
dict.get(n) match {
case Some(output) => {
val (newDict, newCode) = conjecture match {
case Some((code, prefix)) => ((dict + (code -> (prefix + output.head))), code + 1)
case None => (dict, dict.size + 1)
}
(newDict, output :: result, Some(newCode -> output))
}
case None => {
// conjecture being None would be an encoding error
val (code, prefix) = conjecture.get
val output = prefix + prefix.head
(dict + (code -> output), output :: result, Some(code + 1 -> output))
}
}
}
}
result.reverse.mkString("")
}
// test
val text = "TOBEORNOTTOBEORTOBEORNOT"
val compressed = compress(text)
println(compressed)
val result = decompress(compressed)
println(result)

View file

@ -0,0 +1,85 @@
; Get the list reference number for a member or #f if not found
(define (member-string-ref m l)
(define r #f)
(let loop ((i 0))
(if (< i (length l))
(if (not (string=? (list-ref l i) m))
(loop (+ i 1))
(set! r i))))
r)
;; Compress a string with LZW
(define (lzw-compress uncompressed)
(define dictionary '())
(define n 0)
(define result '())
(set! uncompressed (string->list uncompressed))
;; Setup Dictionary
(let dict-setup ((c 0))
(if (> 256 c)
(begin
(set! dictionary (append dictionary
(list (string (integer->char c)))))
(set! n (+ n 1))
(dict-setup (+ c 1)))))
;; Compress the string
(let compress ((w "") (ci 0))
(define c (string (list-ref uncompressed ci)))
(define wc "")
(set! wc (string-append w c))
(if (member-string-ref wc dictionary)
(set! w wc)
(begin
(set! result (append result
(list (member-string-ref w dictionary))))
(set! dictionary (append dictionary (list wc)))
(set! n (+ n 1))
(set! w c)))
(if (eqv? ci (- (length uncompressed) 1))
(set! result (append result
(list (member-string-ref w dictionary))))
(compress w (+ ci 1))))
result)
;; Decompress a LZW compressed string (input should be a list of integers)
(define (lzw-decompress compressed)
(define dictionary '())
(define n 0)
(define result "")
;; Setup Dictionary
(let dict-setup ((c 0))
(if (> 256 c)
(begin
(set! dictionary (append dictionary
(list (string (integer->char c)))))
(set! n (+ n 1))
(dict-setup (+ c 1)))))
;; Decompress the list
(let decompress ((k (list-ref compressed 0)) (ci 0))
(define kn #f)
;; Add to dictionary
(if (> (length compressed) (+ ci 1))
(begin
(set! kn (list-ref compressed (+ ci 1)))
(if (< kn (length dictionary))
(set! dictionary
(append dictionary
(list (string-append
(list-ref dictionary k)
(string (string-ref (list-ref dictionary kn) 0)))))))))
;; Build the resulting string
(set! result (string-append result (list-ref dictionary k)))
(if (not (eqv? ci (- (length compressed) 1)))
(decompress kn (+ ci 1))))
result)
(define compressed (lzw-compress "TOBEORNOTTOBEORTOBEORNOT"))
(display compressed) (newline)
(define decompressed (lzw-decompress compressed))
(display decompressed) (newline)

View file

@ -0,0 +1,75 @@
$ include "seed7_05.s7i";
const func string: lzwCompress (in string: uncompressed) is func
result
var string: compressed is "";
local
var char: ch is ' ';
var hash [string] char: mydict is (hash [string] char).value;
var string: buffer is "";
var string: xstr is "";
begin
for ch range chr(0) to chr(255) do
mydict @:= [str(ch)] ch;
end for;
for ch range uncompressed do
xstr := buffer & str(ch);
if xstr in mydict then
buffer &:= str(ch)
else
compressed &:= str(mydict[buffer]);
mydict @:= [xstr] chr(length(mydict));
buffer := str(ch);
end if;
end for;
if buffer <> "" then
compressed &:= str(mydict[buffer]);
end if;
end func;
const func string: lzwDecompress (in string: compressed) is func
result
var string: uncompressed is "";
local
var char: ch is ' ';
var hash [char] string: mydict is (hash [char] string).value;
var string: buffer is "";
var string: current is "";
var string: chain is "";
begin
for ch range chr(0) to chr(255) do
mydict @:= [ch] str(ch);
end for;
for ch range compressed do
if buffer = "" then
buffer := mydict[ch];
uncompressed &:= buffer;
elsif ch <= chr(255) then
current := mydict[ch];
uncompressed &:= current;
chain := buffer & current;
mydict @:= [chr(length(mydict))] chain;
buffer := current;
else
if ch in mydict then
chain := mydict[ch];
else
chain := buffer & str(buffer[1]);
end if;
uncompressed &:= chain;
mydict @:= [chr(length(mydict))] buffer & str(chain[1]);
buffer := chain;
end if;
end for;
end func;
const proc: main is func
local
var string: compressed is "";
var string: uncompressed is "";
begin
compressed := lzwCompress("TOBEORNOTTOBEORTOBEORNOT");
writeln(literal(compressed));
uncompressed := lzwDecompress(compressed);
writeln(uncompressed);
end func;

View file

@ -0,0 +1,72 @@
# Compress a string to a list of output symbols.
func compress(String uncompressed) -> Array {
# Build the dictionary.
var dict_size = 256
var dictionary = Hash()
for i in range(dict_size) {
dictionary{i.chr} = i.chr
}
var w = ''
var result = []
uncompressed.each { |c|
var wc = w+c
if (dictionary.exists(wc)) {
w = wc
} else {
result << dictionary{w}
# Add wc to the dictionary.
dictionary{wc} = dict_size
dict_size++
w = c
}
}
# Output the code for w.
if (w != '') {
result << dictionary{w}
}
return result
}
# Decompress a list of output ks to a string.
func decompress(Array compressed) -> String {
# Build the dictionary.
var dict_size = 256
var dictionary = Hash()
for i in range(dict_size) {
dictionary{i.chr} = i.chr
}
var w = compressed.shift
var result = w
compressed.each { |k|
var entry = nil
if (dictionary.exists(k)) {
entry = dictionary{k}
} elsif (k == dict_size) {
entry = w+w.first
} else {
die "Bad compressed k: #{k}"
}
result += entry
# Add w+entry[0] to the dictionary.
dictionary{dict_size} = w+entry.first
dict_size++
w = entry
}
return result
}
# How to use:
var compressed = compress('TOBEORNOTTOBEORTOBEORNOT')
say compressed.join(' ')
var decompressed = decompress(compressed)
say decompressed

View file

@ -0,0 +1,65 @@
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
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] = w + String(entry[entry.startIndex])
dictSize += 1
w = entry
}
return result
}
}
let comp = LZW.compress("TOBEORNOTTOBEORTOBEORNOT")
print(comp)
if let decomp = LZW.decompress(comp) {
print(decomp)
}

View file

@ -0,0 +1,60 @@
namespace eval LZW {
variable char2int
variable chars
for {set i 0} {$i < 256} {incr i} {
set char [binary format c $i]
set char2int($char) $i
lappend chars $char
}
}
proc LZW::encode {data} {
variable char2int
array set dict [array get char2int]
set w ""
set result [list]
foreach c [split $data ""] {
set wc $w$c
if {[info exists dict($wc)]} {
set w $wc
} else {
lappend result $dict($w)
set dict($wc) [array size dict]
set w $c
}
}
lappend result $dict($w)
}
proc LZW::decode {cdata} {
variable chars
set dict $chars
set k [lindex $cdata 0]
set w [lindex $dict $k]
set result $w
foreach k [lrange $cdata 1 end] {
set currSizeDict [llength $dict]
if {$k < $currSizeDict} {
set entry [lindex $dict $k]
} elseif {$k == $currSizeDict} {
set entry $w[string index $w 0]
} else {
error "invalid code ($k) in ($cdata)"
}
append result $entry
lappend dict $w[string index $entry 0]
set w $entry
}
return $result
}
set s TOBEORNOTTOBEORTOBEORNOT#
set e [LZW::encode $s] ;# ==> 84 79 66 69 79 82 78 79 84 256 258 260 265 259 261 263 35
set d [LZW::decode $e] ;# ==> TOBEORNOTTOBEORTOBEORNOT#
# or
if {$s eq [LZW::decode [LZW::encode $s]]} then {puts success} else {puts fail} ;# ==> success

View file

@ -0,0 +1,74 @@
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

View file

@ -0,0 +1,60 @@
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)

View file

@ -0,0 +1,105 @@
Function compress(str as String) As String
Dim i as integer
Dim w as String = ""
Dim c as String
Dim strLen as Integer
Dim wc as string
Dim dic() as string
Dim result() as string
Dim lookup as integer
Dim startPos as integer = 0
Dim combined as String
strLen = len(str)
dic = populateDictionary
for i = 1 to strLen
c = str.mid(i, 1)
wc = w + c
startPos = getStartPos(wc)
lookup = findArrayPos(dic, wc, startPos)
if (lookup <> -1) then
w = wc
Else
startPos = getStartPos(w)
lookup = findArrayPos(dic, w, startPos)
if lookup <> -1 then
result.Append(lookup.ToText)
end if
dic.append(wc)
w = c
end if
next i
if (w <> "") then
startPos = getStartPos(w)
lookup = findArrayPos(dic, w, startPos)
result.Append(lookup.ToText)
end if
return join(result, ",")
End Function
Function decompress(str as string) As string
dim comStr() as string
dim w as string
dim result as string
dim comStrLen as integer
dim entry as string
dim dic() as string
dim i as integer
comStr = str.Split(",")
comStrLen = comStr.Ubound
dic = populateDictionary
w = chr(val(comStr(0)))
result = w
for i = 1 to comStrLen
entry = dic(val(comStr(i)))
result = result + entry
dic.append(w + entry.mid(1,1))
w = entry
next i
return result
End Function
Private Function findArrayPos(arr() as String, search as String, start as integer) As Integer
dim arraySize as Integer
dim arrayPosition as Integer = -1
dim i as Integer
arraySize = UBound(arr)
for i = start to arraySize
if (strcomp(arr(i), search, 0) = 0) then
arrayPosition = i
exit
end if
next i
return arrayPosition
End Function
Private Function getStartPos(str as String) As integer
if (len(str) = 1) then
return 0
else
return 255
end if
End Function
Private Function populateDictionary() As string()
dim dic() as string
dim i as integer
for i = 0 to 255
dic.append(Chr(i))
next i
return dic
End Function

View file

@ -0,0 +1,28 @@
fcn lzwCompress(uncompressed){ // text-->list of 12 bit ints
dictionary:=(256).pump(Dictionary(),fcn(n){ return(n.toChar(),n) });
w,compressed:="",List();
foreach c in (uncompressed){
wc:=w+c;
if(dictionary.holds(wc)) w=wc;
else{
compressed.append(dictionary[w]); // 12 bits
dictionary[wc]=dictionary.len();
w=c;
}
}
if(w) compressed.append(dictionary[w]);
compressed
}
fcn lzwUncompress(compressed){ // compressed data-->text
dictionary:=(256).pump(Dictionary(),fcn(n){ return(n,n.toChar()) });
w,decommpressed:=dictionary[compressed[0]],Data(Void,w);
foreach k in (compressed[1,*]){
if(dictionary.holds(k)) entry:=dictionary[k];
else if(k==dictionary.len()) entry:=w+w[0];
else throw(Exception.ValueError("Invalid compressed data"));
decommpressed.append(entry);
dictionary.add(dictionary.len(),w+entry[0]);
w=entry;
}
decommpressed.text
}

View file

@ -0,0 +1,4 @@
compressed:=lzwCompress("TOBEORNOTTOBEORTOBEORNOT");
compressed.toString(*).println();
lzwUncompress(compressed).println();