Run-length encoding: Difference between revisions

Content added Content deleted
(Updated two of the four D versions)
(Updated two D versions)
Line 724: Line 724:


=={{header|D}}==
=={{header|D}}==
===Short Functional Version===
<lang d>import std.algorithm, std.conv, std.array;

alias group encode;

string decode(Group!("a == b", string) enc) {
return join(map!(t => replicate(""~cast(char)t[0], t[1]))(enc));
}

void main() {
auto s = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
assert(decode(encode(s)) == s);
}</lang>
===Basic Imperative Version===
===Basic Imperative Version===
<lang d>import std.stdio, std.array, std.conv;
<lang d>import std.stdio, std.array, std.conv;
Line 774: Line 787:
writeln("Encoded: ", encoded);
writeln("Encoded: ", encoded);
assert(txt == decode(encoded));
assert(txt == decode(encoded));
}</lang>
===Short Functional Version===
<lang d>import std.stdio, std.algorithm, std.conv, std.array;

alias group encode;

string decode(Range)(Range r) {
return join(map!(t => replicate(""~cast(char)t[0], t[1]))(r));
}

void main() {
auto s = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
assert(decode(encode(s)) == s);
}</lang>
}</lang>
===UTF String Version===
===UTF String Version===
D's native string is utf-encoded. This version work for utf string. This code use a [[Variable-length_quantity|Variable-length Quantity]] [[Variable-length_quantity#D|module]].
D's native string is utf-encoded. This version work for utf string. This code use a [[Variable-length_quantity|Variable-length Quantity]] [[Variable-length_quantity#D|module]].


<lang d>import std.stdio ;
<lang d>import std.stdio, std.conv, std.utf, std.string;
import std.conv ;
import vlq;
import std.utf ;
import std.string ;

import vlq ;


struct RLE { // for utf string
struct RLE { // for utf string
ubyte[] encoded ;
ubyte[] encoded;

RLE encode(const string s) {
RLE encode(const string s) {
validate(s) ; // check if s is well-formed utf, throw if not
validate(s); // check if s is well-formed utf, throw if not
encoded.length = 0 ; // reset
encoded.length = 0; // reset
if(s.length == 0) return this ; // empty string
if (s.length == 0) return this; // empty string
string last ;
string last;
VLQ count ; // init value 0
VLQ count;
for(int i = 0 ; i < s.length ;) {
for (int i = 0; i < s.length; ) {
auto k = s.stride(i) ;
auto k = s.stride(i);
auto ucode = cast(string)s[i..i+k] ;
auto ucode = cast(string)s[i .. i+k];
if(i == 0) last = ucode ;
if (i == 0) last = ucode;
if(ucode == last)
if (ucode == last)
count++ ;
count++;
else {
else {
encoded ~= count.toVLQ ~ cast(ubyte[]) last ;
encoded ~= count.toVLQ ~ cast(ubyte[])last;
last = ucode ;
last = ucode;
count = 1 ;
count = 1;
}
}
i += k ;
i += k;
}
}
encoded ~= VLQ(count).toVLQ ~ cast(ubyte[]) last ;
encoded ~= VLQ(count).toVLQ ~ cast(ubyte[])last;
return this ;
return this;
}
}

int opApply(int delegate(ref ulong c, ref string u) dg) {
int opApply(int delegate(ref ulong c, ref string u) dg) {
VLQ count ;
VLQ count;
string ucode ;
string ucode;

for(int i = 0 ; i < encoded.length ;) {
auto k = count.extract(encoded[i..$]) ;
for (int i = 0; i < encoded.length; ) {
i += k ;
auto k = count.extract(encoded[i .. $]);
if(i >= encoded.length)
i += k;
throw new Exception("not valid encoded string") ;
if (i >= encoded.length)
k = stride(cast(string) encoded[i..$], 0) ;
throw new Exception("not valid encoded string");
if(k == 0xff) // not valid utf code point
k = stride(cast(string) encoded[i .. $], 0);
throw new Exception("not valid encoded string") ;
if (k == 0xff) // not valid utf code point
ucode = cast(string) encoded[i..i+k].dup ;
throw new Exception("not valid encoded string");
dg(count.value, ucode) ;
ucode = cast(string)encoded[i .. i+k].dup;
i += k ;
dg(count.value, ucode);
}
i += k;
return 0 ;
}

}
return 0;
}

string toString() {
string toString() {
string res ;
string res;
foreach(ref i, s ; this)
foreach (ref i, s ; this)
if(indexOf(`0123456789#`,s) == -1)
if (indexOf("0123456789#", s) == -1)
res ~= to!string(i) ~ s ;
res ~= text(i) ~ s;
else
else
res ~= to!string(i) ~`#` ~ s ;
res ~= text(i) ~ '#' ~ s;
return res ;
return res;
}
}
string decode() {
string decode() {
string res ;
string res;
foreach(ref i, s ; this)
foreach (ref i, s; this)
res ~= repeat(s, cast(uint)i) ;
res ~= repeat(s, cast(uint)i);
return res ;
return res;
}
}
}
}


void main() {
void main() {
RLE r ;
RLE r;
auto s = "尋尋覓覓冷冷清清淒淒慘慘戚戚\nWWWWWWWWWWWWBWWWWWWWWWWW"
auto s = "尋尋覓覓冷冷清清淒淒慘慘戚戚\nWWWWWWWWWWWWBWWWWWWWWWWW" ~
"WBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW\n"
"WBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW\n" ~
"11#222##333" ;
"11#222##333";
auto f = File("display.txt", "w") ;
auto f = File("display.txt", "w");
f.writeln(s) ;
f.writeln(s);
r.encode(s) ;
r.encode(s);
f.writefln("-----\n%s\n-----\n%s", r, r.decode) ;
f.writefln("-----\n%s\n-----\n%s", r, r.decode);
auto sEncoded = RLE.init.encode(s).encoded ;
auto sEncoded = RLE.init.encode(s).encoded ;
assert(s == RLE(sEncoded).decode , "Not work") ;
assert(s == RLE(sEncoded).decode , "Not work");
}</lang>
}</lang>