Run-length encoding: Difference between revisions

m
(Undo revision 165113 by Grondilu (talk) not a good idea on second thought. Sorry.)
m (→‎{{header|Wren}}: Minor tidy)
 
(186 intermediate revisions by 79 users not shown)
Line 1:
{{Wikipedia|Run-length_encoding}}
 
{{task|Compression}}
[[Category: Encodings]]
 
Given a string containing uppercase characters (A-Z), compress repeated 'runs' of the same character by storing the length of that run, and provide a function to reverse the compression. The output can be anything, as long as you can recreate the input with it.
 
;Task:
Example:
Given a string containing uppercase characters (A-Z), compress repeated 'runs' of the same character by storing the length of that run, and provide a function to reverse the compression.
 
The output can be anything, as long as you can recreate the input with it.
 
 
;Example:
: Input: <code>WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</code>
: Output: <code>12W1B12W3B24W1B14W</code>
 
 
Note: the encoding step in the above example is the same as a step of the [[Look-and-say sequence]].
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F encode(input_string)
V count = 1
V prev = Char("\0")
[(Char, Int)] lst
L(character) input_string
I character != prev
I prev != Char("\0")
lst.append((prev, count))
count = 1
prev = character
E
count++
lst.append((input_string.last, count))
R lst
 
F decode(lst)
V q = ‘’
L(character, count) lst
q ‘’= character * count
R q
 
V value = encode(‘aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa’)
print(‘Encoded value is ’value.map(v -> String(v[1])‘’v[0]))
print(‘Decoded value is ’decode(value))</syntaxhighlight>
 
{{out}}
<pre>
Encoded value is [5a, 6h, 7m, 1u, 7i, 6a]
Decoded value is aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa
</pre>
 
=={{header|8086 Assembly}}==
Output is in hexadecimal but is otherwise correct.
 
<syntaxhighlight lang="asm"> .model small ; 128k .exe file
.stack 1024 ; load SP with 0400h
.data ; no data segment needed
 
.code
start:
 
mov ax,@code
mov ds,ax
mov es,ax
mov si,offset TestString
mov di,offset OutputRam
cld
compressRLE:
lodsb
cmp al,0 ;null terminator?
jz finished_Compressing ;if so, exit
push di
push si
mov cx,0FFFFh ;exit after 65536 reps or the run length ends.
xchg di,si ;scasb only works with es:di so we need to exchange
repz scasb ;repeat until [es:di] != AL
xchg di,si ;exchange back
pop dx ;pop the old SI into DX instead!
pop di
push si
sub si,dx
mov dx,si
pop si
;now the run length is in dx, store it into output ram.
 
push ax
mov al,dl
stosb
pop ax
stosb ;store the letter that corresponds to the run
 
dec si ;we're off by one, so we need to correct for that.
jmp compressRLE ;back to start
finished_Compressing:
 
mov bp, offset OutputRam
mov bx, 32
call doMemDump ;displays a hexdump of the contents of OutputRam
 
 
mov ax,4C00h
int 21h ;exit DOS
TestString byte "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW",0
 
OutputRam byte 256 dup (0)
 
end start</syntaxhighlight>
 
{{out}}
<pre>
0C 57 01 42 0C 57 03 42 .W.B.W.B
18 57 01 42 0E 57 00 00 .W.B.W..
00 00 00 00 00 00 00 00 ........
00 00 00 00 00 00 00 00 ........
</pre>
 
The hexdump above converts to: <code>12W 1B 12W 3B 24W 1B 14W</code>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">BYTE FUNC GetLength(CHAR ARRAY s BYTE pos)
CHAR c
BYTE len
 
c=s(pos)
len=1
DO
pos==+1
IF pos<=s(0) AND s(pos)=c THEN
len==+1
ELSE
EXIT
FI
OD
RETURN (len)
 
BYTE FUNC GetNumber(CHAR ARRAY s BYTE POINTER pos)
BYTE num,len
CHAR ARRAY tmp(5)
 
len=0
DO
len==+1
tmp(len)=s(pos^)
pos^==+1
IF s(pos^)<'0 OR s(pos^)>'9 THEN
EXIT
FI
OD
tmp(0)=len
num=ValB(tmp)
RETURN (num)
 
PROC Append(CHAR ARRAY text,suffix)
BYTE POINTER srcPtr,dstPtr
BYTE len
 
len=suffix(0)
IF text(0)+len>255 THEN
len=255-text(0)
FI
IF len THEN
srcPtr=suffix+1
dstPtr=text+text(0)+1
MoveBlock(dstPtr,srcPtr,len)
text(0)==+suffix(0)
FI
RETURN
 
PROC Encode(CHAR ARRAY in,out)
BYTE pos,len
CHAR ARRAY tmp(5)
 
pos=1 len=0 out(0)=0
WHILE pos<=in(0)
DO
len=GetLength(in,pos)
StrB(len,tmp)
Append(out,tmp)
out(0)==+1
out(out(0))=in(pos)
pos==+len
OD
RETURN
 
PROC Decode(CHAR ARRAY in,out)
BYTE pos,num,i
CHAR c
 
pos=1 out(0)=0
WHILE pos<=in(0)
DO
num=GetNumber(in,@pos)
c=in(pos)
pos==+1
FOR i=1 TO num
DO
out(0)==+1
out(out(0))=c
OD
OD
RETURN
 
PROC Main()
CHAR ARRAY data="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
CHAR ARRAY encoded(256),decoded(256)
 
PrintE("original:")
PrintE(data)
PutE()
 
Encode(data,encoded)
PrintE("encoded:")
PrintE(encoded)
PutE()
 
Decode(encoded,decoded)
PrintE("decoded:")
PrintE(decoded)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Run-length_encoding.png Screenshot from Atari 8-bit computer]
<pre>
original:
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
 
encoded:
12W1B12W3B24W1B14W
 
decoded:
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
procedure Test_Run_Length_Encoding is
Line 60 ⟶ 292:
Put_Line (Encode ("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"));
Put_Line (Decode ("12W1B12W3B24W1B14W"));
end Test_Run_Length_Encoding;</langsyntaxhighlight>
Sample output:
<pre>
Line 75 ⟶ 307:
 
Note: The following uses iterators, eliminating the need of declaring arbitrarily large CHAR arrays for caching.
<langsyntaxhighlight lang="algol68">STRING input := "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
STRING output := "12W1B12W3B24W1B14W";
 
Line 146 ⟶ 378:
print(c)
# OD # );
print(new line)</langsyntaxhighlight>
Output:
<pre>
Encode input: 12W1B12W3B24W1B14W
Decode output: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|Amazing Hopper}}==
<syntaxhighlight lang="c">
/*
TASK BASIC-EMBEBIDO de HOPPER
 
onechar("WB",objetivo)
deja un único carcater de todos los que encuentre consecutivamente,
de la lista de caracteres "WB".
índice:=()
copia el valor de la función entre paréntesis en "índice", pero
deja ese valor en el stack de trabajo, para ser asignado a "largo".
poschar(INICIO, v, objetivo)
entrega la posición donde el caracter dado "v" deja de repetirse
(por eso se resta 1 al resultado).
objetivo+=sublargo
borra los primeros sublargo-ésimo caracteres.
#basic{...} / #(...)
BASIC embebido de Hopper.
*/
 
#include <basico.h>
 
#define INICIO 1
#proto codificar(_X_,_Y_,_Z_)
#proto decodificar(_X_,_Y_)
 
principal {
índice="", largo=0, codificado="", decodificado=""
objetivo = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
 
decimales '0', fijar separador 'NULO'
#basic{
largo = len(índice:=( onechar("WB",objetivo) ) )
print ("Original =",objetivo,NL)
 
codificado = codificar(objetivo, índice, largo)
decodificado = decodificar(codificado, índice)
print ("Codificado =",codificado,"\nDecodificado =",decodificado,NL)
}
terminar
}
 
subrutinas
 
codificar( o, i, l)
v="", sublargo=0
para cada caracter ( v, i, l )
/* deja ésto en el stack de trabajo: */
#( sublargo := (poschar(INICIO, v, o) - 1 ) ), 'v'
o+=sublargo
siguiente
unir esto
retornar
 
decodificar(c, i)
v="", posición=0, l=0
#( l=len(i) )
para cada caracter ( v, i, l )
#basic{
posición = find(v, c)-1
/* deja ésto en el stack de trabajo: */
replicate(v, number(copy(posición,1,c)) )
}
++posición,c+=posición
siguiente
unir esto
retornar
 
</syntaxhighlight>
{{out}}
<pre>
Original =WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Codificado =12W1B12W3B24W1B14W
Decodificado =WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
 
</pre>
 
=={{header|APL}}==
<langsyntaxhighlight APLlang="apl"> ∇ ret←RLL rll;count
[1] count←∣2-/((1,(2≠/rll),1)×⍳1+⍴rll)~0
[2] ret←(⍕count,¨(1,2≠/rll)/rll)~' '
</syntaxhighlight>
</lang>
Sample Output:
<pre>
Line 164 ⟶ 480:
12W1B12W3B24W1B14W
</pre>
 
=={{header|AppleScript}}==
<syntaxhighlight lang="applescript">------------------ RUN-LENGTH ENCODING‎‎ -----------------
 
-- encode :: String -> String
on encode(s)
script go
on |λ|(cs)
if {} ≠ cs then
set c to text 1 of cs
set {chunk, residue} to span(eq(c), rest of cs)
(c & (1 + (length of chunk)) as string) & |λ|(residue)
else
""
end if
end |λ|
end script
|λ|(characters of s) of go
end encode
 
 
-- decode :: String -> String
on decode(s)
script go
on |λ|(cs)
if {} ≠ cs then
set {ds, residue} to span(my isDigit, rest of cs)
set n to (ds as string) as integer
replicate(n, item 1 of cs) & |λ|(residue)
else
""
end if
end |λ|
end script
|λ|(characters of s) of go
end decode
 
 
--------------------------- TEST -------------------------
on run
set src to ¬
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
set encoded to encode(src)
set decoded to decode(encoded)
unlines({encoded, decoded, src = decoded})
end run
 
 
-------------------- GENERIC FUNCTIONS -------------------
 
-- eq :: a -> a -> Bool
on eq(a)
-- True if a and b are equivalent in terms
-- of the AppleScript (=) operator.
script go
on |λ|(b)
a = b
end |λ|
end script
end eq
 
 
-- isDigit :: Char -> Bool
on isDigit(c)
set n to (id of c)
48 ≤ n and 57 ≥ n
end isDigit
 
 
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
 
 
-- Egyptian multiplication - progressively doubling a list, appending
-- stages of doubling to an accumulator where needed for binary
-- assembly of a target length
-- replicate :: Int -> String -> String
on replicate(n, s)
-- Egyptian multiplication - progressively doubling a list,
-- appending stages of doubling to an accumulator where needed
-- for binary assembly of a target length
script p
on |λ|({n})
n ≤ 1
end |λ|
end script
script f
on |λ|({n, dbl, out})
if (n mod 2) > 0 then
set d to out & dbl
else
set d to out
end if
{n div 2, dbl & dbl, d}
end |λ|
end script
set xs to |until|(p, f, {n, s, ""})
item 2 of xs & item 3 of xs
end replicate
 
 
-- span :: (a -> Bool) -> [a] -> ([a], [a])
on span(p, xs)
-- The longest (possibly empty) prefix of xs
-- that contains only elements satisfying p,
-- tupled with the remainder of xs.
-- span(p, xs) eq (takeWhile(p, xs), dropWhile(p, xs))
script go
property mp : mReturn(p)
on |λ|(vs)
if {} ≠ vs then
set x to item 1 of vs
if |λ|(x) of mp then
set {ys, zs} to |λ|(rest of vs)
{{x} & ys, zs}
else
{{}, vs}
end if
else
{{}, {}}
end if
end |λ|
end script
|λ|(xs) of go
end span
 
 
-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set s to xs as text
set my text item delimiters to dlm
s
end unlines
 
 
-- until :: (a -> Bool) -> (a -> a) -> a -> a
on |until|(p, f, x)
set v to x
set mp to mReturn(p)
set mf to mReturn(f)
repeat until mp's |λ|(v)
set v to mf's |λ|(v)
end repeat
v
end |until|</syntaxhighlight>
{{Out}}
<pre>W12B1W12B3W24B1W14
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
true</pre>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">runlengthEncode: function [s][
join map chunk split s => [&] 'x ->
(to :string size x) ++ first x
]
 
runlengthDecode: function [s][
result: new ""
loop (chunk split s 'x -> positive? size match x {/\d+/}) [a,b] ->
'result ++ repeat first b to :integer join to [:string] a
return result
]
 
str: "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
 
encoded: runlengthEncode str
print ["encoded:" encoded]
 
decoded: runlengthDecode encoded
print ["decoded:" decoded]
 
if decoded=str -> print "\nSuccess!"</syntaxhighlight>
 
{{out}}
 
<pre>encoded: 12W1B12W3B24W1B14W
decoded: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
 
Success!</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">MsgBox % key := rle_encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
MsgBox % rle_decode(key)
 
Line 200 ⟶ 712:
}
Return output
}</langsyntaxhighlight>
 
=={{header|AWK}}==
Line 209 ⟶ 721:
'''Encoding'''
 
<langsyntaxhighlight lang="awk">BEGIN {
FS=""
}
Line 224 ⟶ 736:
}
printf("%d%c", j, cp)
}</langsyntaxhighlight>
 
'''Decoding'''
 
<langsyntaxhighlight lang="awk">BEGIN {
RS="[0-9]+[^0-9]"
final = "";
Line 240 ⟶ 752:
END {
print final
}</langsyntaxhighlight>
 
=={{header|BaCon}}==
<syntaxhighlight lang="qbasic">FUNCTION Rle_Encode$(txt$)
 
LOCAL result$, c$ = LEFT$(txt$, 1)
LOCAL total = 1
 
FOR x = 2 TO LEN(txt$)
IF c$ = MID$(txt$, x, 1) THEN
INCR total
ELSE
result$ = result$ & STR$(total) & c$
c$ = MID$(txt$, x, 1)
total = 1
END IF
NEXT
 
RETURN result$ & STR$(total) & c$
 
END FUNCTION
 
FUNCTION Rle_Decode$(txt$)
 
LOCAL nr$, result$
 
FOR x = 1 TO LEN(txt$)
IF REGEX(MID$(txt$, x, 1), "[[:digit:]]") THEN
nr$ = nr$ & MID$(txt$, x, 1)
ELSE
result$ = result$ & FILL$(VAL(nr$), ASC(MID$(txt$, x, 1)))
nr$ = ""
END IF
NEXT
 
RETURN result$
 
END FUNCTION
 
rle_data$ = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
 
PRINT "RLEData: ", rle_data$
encoded$ = Rle_Encode$(rle_data$)
PRINT "Encoded: ", encoded$
PRINT "Decoded: ", Rle_Decode$(encoded$)</syntaxhighlight>
{{out}}
<pre>RLEData: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Encoded: 12W1B12W3B24W1B14W
Decoded: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|BASIC}}==
Line 248 ⟶ 809:
{{trans|PowerBASIC}}
 
<langsyntaxhighlight lang="qbasic">DECLARE FUNCTION RLDecode$ (i AS STRING)
DECLARE FUNCTION RLEncode$ (i AS STRING)
 
Line 302 ⟶ 863:
outP = outP + tmp2
RLEncode$ = outP
END FUNCTION</langsyntaxhighlight>
 
Sample output (last one shows errors from using numbers in input string):
Line 320 ⟶ 881:
111r
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
==={{header|Applesoft BASIC}}===
 
<syntaxhighlight lang="basic"> 10 I$ = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
20 GOSUB 100ENCODE
30 GOSUB 200DECODE
40 PRINT "INPUT: ";I$
50 PRINT "OUTPUT: ";
60 GOSUB 250 PRINT
70 END
100 O$ = MID$ (I$,1,1):N$ = MID$ ( CHR$ (0),1, LEN (O$)): IF LEN (I$) < 2 THEN RETURN
110 FOR I = 2 TO LEN (I$):C$ = MID$ (I$,I,1): IF C$ < > RIGHT$ (O$,1) THEN O$ = O$ + C$:N$ = N$ + CHR$ (0): NEXT I: RETURN
120 N$ = MID$ (N$,1, LEN (O$) - 1) + CHR$ ( ASC ( MID$ (N$, LEN (O$))) + 1): NEXT I: RETURN
200 I$ = "": IF LEN (O$) THEN FOR I = 1 TO LEN (O$): FOR J = 0 TO ASC ( MID$ (N$,I)):I$ = I$ + MID$ (O$,I,1): NEXT J,I
210 RETURN
250 IF LEN (O$) THEN FOR I = 1 TO LEN (O$): PRINT ASC ( MID$ (N$,I)) + 1; MID$ (O$,I,1);: NEXT I
260 RETURN
</syntaxhighlight>
{{out}}
<pre>INPUT: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
OUTPUT: 12W1B12W3B24W1B14W</pre>
 
=={{header|BASIC256}}==
<syntaxhighlight lang="basic256">
function FBString(lon, cad$)
# Definimos la función String en BASIC256
cadena$ = ""
for a = 1 to lon
cadena$ += cad$
next a
return cadena$
end function
 
function RLDecode(i$)
rCount$ = "" : outP$ = ""
 
for Loop0 = 1 to length(i$)
m$ = mid(i$, Loop0, 1)
begin case
case m$ = "0"
rCount$ += m$
case m$ = "1"
rCount$ += m$
case m$ = "2"
rCount$ += m$
case m$ = "3"
rCount$ += m$
case m$ = "4"
rCount$ += m$
case m$ = "5"
rCount$ += m$
case m$ = "6"
rCount$ += m$
case m$ = "7"
rCount$ += m$
case m$ = "8"
rCount$ += m$
case m$ = "9"
rCount$ += m$
else
if length(rCount$) then
outP$ += FBString(int(rCount$), m$)
rCount$ = ""
else
outP$ += m$
end if
end case
next Loop0
 
RLDecode = outP$
end function
 
function RLEncode(i$)
outP$ = ""
tmp1 = mid(i$, 1, 1)
tmp2 = tmp1
rCount = 1
 
for Loop0 = 2 to length(i$)
tmp1 = mid(i$, Loop0, 1)
if tmp1 <> tmp2 then
outP$ += string(rCount) + tmp2
tmp2 = tmp1
rCount = 1
else
rCount += 1
end if
next Loop0
 
outP$ += replace(string(rCount)," ", "")
outP$ += tmp2
RLEncode = outP$
end function
 
input "Type something: ", initial
encoded$ = RLEncode(initial)
decoded$ = RLDecode(encoded$)
print initial
print encoded$
print decoded$
end
</syntaxhighlight>
{{out}}
La salida es similar a la de [[#BASIC|BASIC]], mostrada arriba.
 
=={{header|BBC BASIC}}==
The run counts are indicated by means of character codes in the range 131 to 255.
<langsyntaxhighlight lang="bbcbasic"> input$ = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
PRINT "Input: " input$
rle$ = FNencodeRLE(input$)
Line 358 ⟶ 1,022:
ENDIF
ENDWHILE
= o$</langsyntaxhighlight>
 
=={{header|Befunge}}==
Not the same format as in the example,it puts "n\n" at the beginning so you can pipe the output back in and receive the input.
Pipe the output of the program-it's more reliable.
{{works with|CCBI|2.1}}
<syntaxhighlight lang="befunge"> ~"y"- ~$ v
<temp var for when char changes
format:
first,'n' and a newline. :
a char then a v _"n",v
number then a space continuously 9
example: 1
n > v ,+<
a5 b2
decoded:aaaaabb
the program is ended using decoder
Ctrl-C on linux,or alt-f4
on windows.copy the output >\v encoder
of the program somewhere ^_ $ v
to encode press y : > $11g:, v
to decode pipe file in >1-^ ~ v +1\<
the output of the encoder \ v< $ ^ .\_^
starts with n,this is so ^,:<\&~< _~:,>1>\:v>^
you can pipe it straight in ^ <
~
the spaces seem to be a annoying thing :
thanks to CCBI...if a interpreter dosen't 1
create them it's non-conforming and thus 1
the validity of this program is NOT affected p-
>^
--written by Gamemanj,for Rosettacode</syntaxhighlight>
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat"> ( run-length
= character otherCharacter acc begin end
. :?acc
Line 382 ⟶ 1,077:
)
& run-length$WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</syntaxhighlight>
</lang>
<pre> 12W1B12W3B24W1B14W</pre>
 
=={{header|Burlesque}}==
<langsyntaxhighlight lang="burlesque">
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
=[{^^[~\/L[Sh}\m
</syntaxhighlight>
</lang>
 
=={{header|C}}==
Encoder that can deal with byte streams. Can encode/decode any byte values and any length with reasonable efficiency. Also showing OO and polymophism with structs.
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <stdlib.h>
 
typedef struct stream_t stream_t, *stream;
struct stream_t {
/* get funcitonfunction is supposed to return a byte value (0-255),
or -1 to signify end of input */
int (*get)(stream);
Line 539 ⟶ 1,234:
 
return 0;
}</langsyntaxhighlight>
 
See [[Run-length encoding/C]]
 
=={{header|C++ sharp|C#}}==
=== Linq ===
{{libheader|boost}}
<!--Martin Freedman 22/02/2018-->
<lang cpp>#include <iostream>
<syntaxhighlight lang="csharp">using System.Collections.Generic;
#include <string>
using System.Linq;
#include <sstream>
using static System.Console;
#include <boost/regex.hpp>
using static System.Linq.Enumerable;
#include <cstdlib>
 
namespace RunLengthEncoding
std::string encode ( const std::string & ) ;
{
std::string decode ( const std::string & ) ;
static class Program
{
public static string Encode(string input) => input.Length ==0 ? "" : input.Skip(1)
.Aggregate((t:input[0].ToString(),o:Empty<string>()),
(a,c)=>a.t[0]==c ? (a.t+c,a.o) : (c.ToString(),a.o.Append(a.t)),
a=>a.o.Append(a.t).Select(p => (key: p.Length, chr: p[0])))
.Select(p=> $"{p.key}{p.chr}")
.StringConcat();
 
public static string Decode(string input) => input
int main( ) {
.Aggregate((t: "", o: Empty<string>()), (a, c) => !char.IsDigit(c) ? ("", a.o.Append(a.t+c)) : (a.t + c,a.o)).o
std::string to_encode ( "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" ) ;
.Select(p => new string(p.Last(), int.Parse(string.Concat(p.Where(char.IsDigit)))))
std::cout << to_encode << " encoded:" << std::endl ;
.StringConcat();
std::string encoded ( encode ( to_encode ) ) ;
std::cout << encoded << std::endl ;
std::string decoded ( decode( encoded ) ) ;
std::cout << "Decoded again:\n" ;
std::cout << decoded << std::endl ;
if ( to_encode == decoded )
std::cout << "It must have worked!\n" ;
return 0 ;
}
 
private static string StringConcat(this IEnumerable<string> seq) => string.Concat(seq);
std::string encode( const std::string & to_encode ) {
std::string::size_type found = 0 , nextfound = 0 ;
public static void Main(string[] args)
std::ostringstream oss ;
{
nextfound = to_encode.find_first_not_of( to_encode[ found ] , found ) ;
const string raw = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
while ( nextfound != std::string::npos ) {
const string encoded = "12W1B12W3B24W1B14W";
oss << nextfound - found ;
oss << to_encode[ found ] ;
found = nextfound ;
nextfound = to_encode.find_first_not_of( to_encode[ found ] , found ) ;
}
//since we must not discard the last characters we add them at the end of the string
std::string rest ( to_encode.substr( found ) ) ;//last run of characters starts at position found
oss << rest.length( ) << to_encode[ found ] ;
return oss.str( ) ;
}
 
WriteLine($"raw = {raw}");
std::string decode ( const std::string & to_decode ) {
WriteLine($"encoded = {encoded}");
boost::regex e ( "(\\d+)(\\w)" ) ;
WriteLine($"Encode(raw) = encoded = {Encode(raw)}");
boost::match_results<std::string::const_iterator> matches ;
WriteLine($"Decode(encode) = {Decode(encoded)}");
std::ostringstream oss ;
WriteLine($"Decode(Encode(raw)) = {Decode(Encode(raw)) == raw}");
std::string::const_iterator start = to_decode.begin( ) , end = to_decode.end( ) ;
ReadLine();
while ( boost::regex_search ( start , end , matches , e ) ) {
}
std::string numberstring ( matches[ 1 ].first , matches[ 1 ].second ) ;
}
int number = atoi( numberstring.c_str( ) ) ;
}</syntaxhighlight>
std::string character ( matches[ 2 ].first , matches[ 2 ].second ) ;
Output:
for ( int i = 0 ; i < number ; i++ )
<pre>raw = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
oss << character ;
encoded = 12W1B12W3B24W1B14W
start = matches[ 2 ].second ;
Encode(raw) = encoded = 12W1B12W3B24W1B14W
}
Decode(encode) = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
return oss.str( ) ;
Decode(Encode(raw)) = True
}</lang>
</pre>
 
Many solutions do not follow the suggested output guideline in the challenge (not helped by its wording), instead producing a list of tuples or equivalent. This is much simpler (especially for decode) and the following provides an equivalent of those (IMHO deficient) solutions, to make comparisons easier.
=={{header|C sharp|C#}}==
<syntaxhighlight lang="csharp">using System.Collections.Generic;
using System.Linq;
using static System.Console;
namespace RunLengthEncoding
{
static class Program
{
public static string Encode(string input) => input.Length ==0 ? "" : input.Skip(1)
.Aggregate((t:input[0].ToString(),o:Empty<string>()),
(a,c)=>a.t[0]==c ? (a.t+c,a.o) : (c.ToString(),a.o.Append(a.t)),
a=>a.o.Append(a.t).Select(p => (key: p.Length, chr: p[0])));
 
public static string Decode(IEnumerable<(int i , char c)> input) =>
string.Concat(input.Select(t => new string(t.c, t.i)));
 
public static void Main(string[] args)
{
const string raw = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
var encoded = new[] { (12, 'W'), (1, 'B'), (12, 'W'), (3, 'B'), (24, 'W'), (1, 'B'), (14, 'W') };
 
WriteLine($"raw = {raw}");
WriteLine($"Encode(raw) = encoded = {Encode(raw).TupleListToString()}");
WriteLine($"Decode(encoded) = {Decode(encoded)}");
WriteLine($"Decode(Encode(raw)) = {Decode(Encode(raw)) == raw}");
ReadLine();
}
private static string TupleListToString(this IEnumerable<(int i, char c)> list) =>
string.Join(",", list.Select(t => $"[{t.i},{t.c}]"));
}
}</syntaxhighlight>
Output:
<pre>raw = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Encode(raw) = encoded = [12,W],[1,B],[12,W],[3,B],[24,W],[1,B],[14,W]
Decode(encoded) = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Decode(Encode(raw)) = True
</pre>
Stringbuilder version. Might be more performant but mixes output formatting with encoding/decoding logic.
<!--Martin Freedman 22/02/2018-->
<syntaxhighlight lang="csharp">using System.Collections.Generic;
using System.Linq;
using static System.Console;
using static System.Text;
 
namespace RunLengthEncoding
{
static class Program
{
public static string Encode(string input) => input.Length == 0 ? "" : input.Skip(1)
.Aggregate((len: 1, chr: input[0], sb: new StringBuilder()),
(a, c) => a.chr == c ? (a.len + 1, a.chr, a.sb)
: (1, c, a.sb.Append(a.len).Append(a.chr))),
a => a.sb.Append(a.len).Append(a.chr)))
.ToString();
 
public static string Decode(string input) => input
.Aggregate((t: "", sb: new StringBuilder()),
(a, c) => !char.IsDigit(c) ? ("", a.sb.Append(new string(c, int.Parse(a.t))))
: (a.t + c, a.sb))
.sb.ToString();
public static void Main(string[] args)
{
const string raw = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
const string encoded = "12W1B12W3B24W1B14W";
 
WriteLine($"raw = {raw}");
WriteLine($"encoded = {encoded}");
WriteLine($"Encode(raw) = encoded = {Encode(raw)}");
WriteLine($"Decode(encode) = {Decode(encoded)}");
WriteLine($"Decode(Encode(raw)) = {Decode(Encode(raw)) == raw}");
ReadLine();
}
}
}</syntaxhighlight>
Output:
<pre>raw = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
encoded = 12W1B12W3B24W1B14W
Encode(raw) = encoded = 12W1B12W3B24W1B14W
Decode(encode) = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Decode(Encode(raw)) = True
</pre>
 
=== Imperative ===
This example only works if there are no digits in the string to be encoded and then decoded.
 
<syntaxhighlight lang="csharp"> public static void Main(string[] args)
<lang csharp>
public static void Main(string[] args)
{
string input = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
Line 652 ⟶ 1,420:
}
return sb.ToString();
}</syntaxhighlight>
 
</lang>
=== RegEx ===
Somewhat shorter, using Regex.Replace with MatchEvaluator (using C#2 syntax only):
<langsyntaxhighlight lang="csharp">using System;
using System.Text.RegularExpressions;
 
Line 691 ⟶ 1,460:
});
}
}</langsyntaxhighlight>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <algorithm>
#include <array>
#include <iterator>
#include <limits>
#include <tuple>
 
namespace detail_ {
 
// For constexpr digit<->number conversions.
constexpr auto digits = std::array{'0','1','2','3','4','5','6','7','8','9'};
 
// Helper function to encode a run-length.
template <typename OutputIterator>
constexpr auto encode_run_length(std::size_t n, OutputIterator out)
{
constexpr auto base = digits.size();
// Determine the number of digits needed.
auto const num_digits = [base](auto n)
{
auto d = std::size_t{1};
while ((n /= digits.size()))
++d;
return d;
}(n);
// Helper lambda to raise the base to an integer power.
auto base_power = [base](auto n)
{
auto res = decltype(base){1};
for (auto i = decltype(n){1}; i < n; ++i)
res *= base;
return res;
};
// From the most significant digit to the least, output the digit.
for (auto i = decltype(num_digits){0}; i < num_digits; ++i)
*out++ = digits[(n / base_power(num_digits - i)) % base];
return out;
}
 
// Helper function to decode a run-length.
// As of C++20, this can be constexpr, because std::find() is constexpr.
// Before C++20, it can be constexpr by emulating std::find().
template <typename InputIterator>
auto decode_run_length(InputIterator first, InputIterator last)
{
auto count = std::size_t{0};
while (first != last)
{
// If the next input character is not a digit, we're done.
auto const p = std::find(digits.begin(), digits.end(), *first);
if (p == digits.end())
break;
// Convert the digit to a number, and append it to the size.
count *= digits.size();
count += std::distance(digits.begin(), p);
// Move on to the next input character.
++first;
}
return std::tuple{count, first};
}
 
} // namespace detail_
 
template <typename InputIterator, typename OutputIterator>
constexpr auto encode(InputIterator first, InputIterator last, OutputIterator out)
{
while (first != last)
{
// Read the next value.
auto const value = *first++;
// Increase the count as long as the next value is the same.
auto count = std::size_t{1};
while (first != last && *first == value)
{
++count;
++first;
}
// Write the value and its run length.
out = detail_::encode_run_length(count, out);
*out++ = value;
}
return out;
}
 
// As of C++20, this can be constexpr, because std::find() and
// std::fill_n() are constexpr (and decode_run_length() can be
// constexpr, too).
// Before C++20, it can be constexpr by emulating std::find() and
// std::fill_n().
template <typename InputIterator, typename OutputIterator>
auto decode(InputIterator first, InputIterator last, OutputIterator out)
{
while (first != last)
{
using detail_::digits;
// Assume a run-length of 1, then try to decode the actual
// run-length, if any.
auto count = std::size_t{1};
if (std::find(digits.begin(), digits.end(), *first) != digits.end())
std::tie(count, first) = detail_::decode_run_length(first, last);
// Write the run.
out = std::fill_n(out, count, *first++);
}
return out;
}
 
template <typename Range, typename OutputIterator>
constexpr auto encode(Range&& range, OutputIterator out)
{
using std::begin;
using std::end;
return encode(begin(range), end(range), out);
}
 
template <typename Range, typename OutputIterator>
auto decode(Range&& range, OutputIterator out)
{
using std::begin;
using std::end;
return decode(begin(range), end(range), out);
}
 
// Sample application and checking ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
#include <iostream>
#include <string_view>
 
int main()
{
using namespace std::literals;
constexpr auto test_string = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"sv;
std::cout << "Input: \"" << test_string << "\"\n";
std::cout << "Output: \"";
// No need for a temporary string - can encode directly to cout.
encode(test_string, std::ostreambuf_iterator<char>{std::cout});
std::cout << "\"\n";
auto encoded_str = std::string{};
auto decoded_str = std::string{};
encode(test_string, std::back_inserter(encoded_str));
decode(encoded_str, std::back_inserter(decoded_str));
std::cout.setf(std::cout.boolalpha);
std::cout << "Round trip works: " << (test_string == decoded_str) << '\n';
}</syntaxhighlight>
 
{{libheader|boost}}
<syntaxhighlight lang="cpp">#include <iostream>
#include <string>
#include <sstream>
#include <boost/regex.hpp>
#include <cstdlib>
 
std::string encode ( const std::string & ) ;
std::string decode ( const std::string & ) ;
 
int main( ) {
std::string to_encode ( "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" ) ;
std::cout << to_encode << " encoded:" << std::endl ;
std::string encoded ( encode ( to_encode ) ) ;
std::cout << encoded << std::endl ;
std::string decoded ( decode( encoded ) ) ;
std::cout << "Decoded again:\n" ;
std::cout << decoded << std::endl ;
if ( to_encode == decoded )
std::cout << "It must have worked!\n" ;
return 0 ;
}
 
std::string encode( const std::string & to_encode ) {
std::string::size_type found = 0 , nextfound = 0 ;
std::ostringstream oss ;
nextfound = to_encode.find_first_not_of( to_encode[ found ] , found ) ;
while ( nextfound != std::string::npos ) {
oss << nextfound - found ;
oss << to_encode[ found ] ;
found = nextfound ;
nextfound = to_encode.find_first_not_of( to_encode[ found ] , found ) ;
}
//since we must not discard the last characters we add them at the end of the string
std::string rest ( to_encode.substr( found ) ) ;//last run of characters starts at position found
oss << rest.length( ) << to_encode[ found ] ;
return oss.str( ) ;
}
 
std::string decode ( const std::string & to_decode ) {
boost::regex e ( "(\\d+)(\\w)" ) ;
boost::match_results<std::string::const_iterator> matches ;
std::ostringstream oss ;
std::string::const_iterator start = to_decode.begin( ) , end = to_decode.end( ) ;
while ( boost::regex_search ( start , end , matches , e ) ) {
std::string numberstring ( matches[ 1 ].first , matches[ 1 ].second ) ;
int number = atoi( numberstring.c_str( ) ) ;
std::string character ( matches[ 2 ].first , matches[ 2 ].second ) ;
for ( int i = 0 ; i < number ; i++ )
oss << character ;
start = matches[ 2 ].second ;
}
return oss.str( ) ;
}</syntaxhighlight>
 
=={{header|Ceylon}}==
<syntaxhighlight lang="ceylon">shared void run() {
"Takes a string such as aaaabbbbbbcc and returns 4a6b2c"
String compress(String string) {
if (exists firstChar = string.first) {
if (exists index = string.firstIndexWhere((char) => char != firstChar)) {
return "``index````firstChar````compress(string[index...])``";
}
else {
return "``string.size````firstChar``";
}
}
else {
return "";
}
}
"Takes a string such as 4a6b2c and returns aaaabbbbbbcc"
String decompress(String string) =>
let (runs = string.split(Character.letter, false).paired)
"".join {
for ([length, char] in runs)
if (is Integer int = Integer.parse(length))
char.repeat(int)
};
assert (compress("aaaabbbbbaa") == "4a5b2a");
assert (decompress("4a6b2c") == "aaaabbbbbbcc");
assert (compress("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW") == "12W1B12W3B24W1B14W");
assert (decompress("24a") == "aaaaaaaaaaaaaaaaaaaaaaaa");
}</syntaxhighlight>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(defn compress [s]
(->> (partition-by identity s) (mapcat (juxt count first)) (apply str)))
 
Line 700 ⟶ 1,721:
(->> (re-seq #"(\d+)([A-Z])" s)
(mapcat (fn [[_ n ch]] (repeat (Integer/parseInt n) ch)))
(apply str)))</langsyntaxhighlight>
 
=={{header|COBOL}}==
{{works with|GNU Cobol|2.0}}
<syntaxhighlight lang="cobol"> >>SOURCE FREE
IDENTIFICATION DIVISION.
PROGRAM-ID. run-length-encoding.
 
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
REPOSITORY.
FUNCTION encode
FUNCTION decode
.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 input-str PIC A(100).
01 encoded PIC X(200).
01 decoded PIC X(200).
 
PROCEDURE DIVISION.
ACCEPT input-str
MOVE encode(FUNCTION TRIM(input-str)) TO encoded
DISPLAY "Encoded: " FUNCTION TRIM(encoded)
DISPLAY "Decoded: " FUNCTION TRIM(decode(encoded))
.
END PROGRAM run-length-encoding.
 
 
IDENTIFICATION DIVISION.
FUNCTION-ID. encode.
 
DATA DIVISION.
LOCAL-STORAGE SECTION.
01 str-len PIC 9(3) COMP.
 
01 i PIC 9(3) COMP.
 
01 current-char PIC A.
 
01 num-chars PIC 9(3) COMP.
01 num-chars-disp PIC Z(3).
 
01 encoded-pos PIC 9(3) COMP VALUE 1.
 
LINKAGE SECTION.
01 str PIC X ANY LENGTH.
 
01 encoded PIC X(200).
 
PROCEDURE DIVISION USING str RETURNING encoded.
MOVE FUNCTION LENGTH(str) TO str-len
MOVE str (1:1) TO current-char
MOVE 1 TO num-chars
PERFORM VARYING i FROM 2 BY 1 UNTIL i > str-len
IF str (i:1) <> current-char
CALL "add-num-chars" USING encoded, encoded-pos,
CONTENT current-char, num-chars
MOVE str (i:1) TO current-char
MOVE 1 TO num-chars
ELSE
ADD 1 TO num-chars
END-IF
END-PERFORM
 
CALL "add-num-chars" USING encoded, encoded-pos, CONTENT current-char,
num-chars
.
END FUNCTION encode.
 
IDENTIFICATION DIVISION.
PROGRAM-ID. add-num-chars.
 
DATA DIVISION.
WORKING-STORAGE SECTION.
01 num-chars-disp PIC Z(3).
 
LINKAGE SECTION.
01 str PIC X(200).
 
01 current-pos PIC 9(3) COMP.
 
01 char-to-encode PIC X.
 
01 num-chars PIC 9(3) COMP.
 
PROCEDURE DIVISION USING str, current-pos, char-to-encode, num-chars.
MOVE num-chars TO num-chars-disp
MOVE FUNCTION TRIM(num-chars-disp) TO str (current-pos:3)
ADD FUNCTION LENGTH(FUNCTION TRIM(num-chars-disp)) TO current-pos
MOVE char-to-encode TO str (current-pos:1)
ADD 1 TO current-pos
.
END PROGRAM add-num-chars.
 
 
IDENTIFICATION DIVISION.
FUNCTION-ID. decode.
 
DATA DIVISION.
LOCAL-STORAGE SECTION.
01 encoded-pos PIC 9(3) COMP VALUE 1.
01 decoded-pos PIC 9(3) COMP VALUE 1.
 
01 num-of-char PIC 9(3) COMP VALUE 0.
 
LINKAGE SECTION.
01 encoded PIC X(200).
 
01 decoded PIC X(100).
 
PROCEDURE DIVISION USING encoded RETURNING decoded.
PERFORM VARYING encoded-pos FROM 1 BY 1
UNTIL encoded (encoded-pos:2) = SPACES OR encoded-pos > 200
IF encoded (encoded-pos:1) IS NUMERIC
COMPUTE num-of-char = num-of-char * 10
+ FUNCTION NUMVAL(encoded (encoded-pos:1))
ELSE
PERFORM UNTIL num-of-char = 0
MOVE encoded (encoded-pos:1) TO decoded (decoded-pos:1)
ADD 1 TO decoded-pos
SUBTRACT 1 FROM num-of-char
END-PERFORM
END-IF
END-PERFORM
.
END FUNCTION decode.</syntaxhighlight>
 
{{out}}
<pre>
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Encoded: 12W1B12W3B24W1B14W
Decoded: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|CoffeeScript}}==
 
<langsyntaxhighlight lang="coffeescript">encode = (str) ->
str.replace /(.)\1*/g, (w) ->
w[0] + w.length
Line 714 ⟶ 1,869:
console.log s = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
console.log encode s
console.log decode encode s</langsyntaxhighlight>
 
<pre>
Line 724 ⟶ 1,879:
The following version encodes the number of ocurrences as an unicode character. You can change the way it looks by rotating the offset.
 
<langsyntaxhighlight lang="coffeescript">encode = (str, offset = 75) ->
str.replace /(.)\1*/g, (w) ->
w[0] + String.fromCharCode(offset+w.length)
Line 731 ⟶ 1,886:
str.split('').map((w,i) ->
if not (i%2) then w else new Array(+w.charCodeAt(0)-offset).join(str[i-1])
).join('')</langsyntaxhighlight>
 
<pre>
Line 743 ⟶ 1,898:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun group-similar (sequence &key (test 'eql))
(loop for x in (rest sequence)
with temp = (subseq sequence 0 1)
Line 765 ⟶ 1,920:
 
(run-length-encode "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
(run-length-decode '((#\W 12) (#\B 1) (#\W 12) (#\B 3) (#\W 24) (#\B 1)))</langsyntaxhighlight>
 
=={{header|D}}==
===Short Functional Version===
<langsyntaxhighlight lang="d">import std.algorithm, std.array;
 
alias encode = group;
Line 781 ⟶ 1,936:
"WWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
assert(s.encode.decode.equal(s));
}</langsyntaxhighlight>
 
===Basic Imperative Version===
<langsyntaxhighlight lang="d">import std.stdio, std.array, std.conv;
 
// Similar to the 'look and say' function.
string encode(in string input) pure nothrow @safe {
if (input.empty) return input;
return input;
char last = input[$ - 1];
string output;
int count;
 
foreach_reverse (immutable c; input) {
if (c == last) {
count++;
} else {
output = text(count).text ~ last ~ output;
count = 1;
last = c;
Line 803 ⟶ 1,959:
}
 
return text(count).text ~ last ~ output;
}
 
string decode(in string input) pure /*@safe*/ {
string i, result;
 
foreach (immutable c; input)
switch (c) {
case '0': .. case '9':
Line 818 ⟶ 1,974:
throw new Exception("Can not repeat a letter " ~
"without a number of repetitions");
result ~= replicate([c], .replicate(i.to!int(i));
i.length = 0;
break;
default:
throw new Exception("'" ~ c ~ "' is not alphanumeric");
"' is not alphanumeric");
}
 
Line 833 ⟶ 1,988:
"WWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
writeln("Input: ", txt);
immutable encoded = encode(txt).encode;
writeln("Encoded: ", encoded);
assert(txt == decode(encoded).decode);
}</langsyntaxhighlight>
{{out}}
<pre>Input: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Encoded: 12W1B12W3B24W1B14W</pre>
 
===UTF String Version===
D's native string is utf-encoded. This version works for utf string, and uses a [[Variable-length_quantity|Variable-length Quantity]] [[Variable-length_quantity#D|module]].
 
<langsyntaxhighlight lang="d">import std.stdio, std.conv, std.utf, std.array;
import vlq;
 
Line 921 ⟶ 2,077:
auto sEncoded = RLE.init.encode(s).encoded ;
assert(s == RLE(sEncoded).decode(), "Not work");
}</langsyntaxhighlight>
 
output from "display.txt":
Line 942 ⟶ 2,098:
 
The code looks more complex than the third Python version because this also handles digits by escaping them with #.
<langsyntaxhighlight lang="d">import std.stdio, std.conv, std.array, std.regex, std.utf,
std.algorithm;
 
Line 973 ⟶ 2,129:
"11#222##333";
assert(s == reDecode(reEncode(s)));
}</langsyntaxhighlight>
 
=={{header|Déjà Vu}}==
<syntaxhighlight lang="dejavu">rle:
if not dup:
drop
return []
 
swap ]
 
local :source chars
pop-from source
1
for c in source:
if = c over:
++
else:
1 c &
&
return [
 
rld:
)
for pair in swap:
repeat &< pair:
&> pair
concat(
 
 
rle "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
!. dup
!. rld</syntaxhighlight>
{{out}}
<pre>[ & 12 "W" & 1 "B" & 12 "W" & 3 "B" & 24 "W" & 1 "B" & 14 "W" ]
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
<syntaxhighlight lang="delphi">
program RunLengthTest;
 
{$APPTYPE CONSOLE}
 
uses
System.SysUtils;
 
type
TRLEPair = record
count: Integer;
letter: Char;
end;
 
TRLEncoded = TArray<TRLEPair>;
 
TRLEncodedHelper = record helper for TRLEncoded
public
procedure Clear;
function Add(c: Char): Integer;
procedure Encode(Data: string);
function Decode: string;
function ToString: string;
end;
 
{ TRLEncodedHelper }
 
function TRLEncodedHelper.Add(c: Char): Integer;
begin
SetLength(self, length(self) + 1);
Result := length(self) - 1;
with self[Result] do
begin
count := 1;
letter := c;
end;
end;
 
procedure TRLEncodedHelper.Clear;
begin
SetLength(self, 0);
end;
 
function TRLEncodedHelper.Decode: string;
var
p: TRLEPair;
begin
Result := '';
for p in Self do
Result := Result + string.Create(p.letter, p.count);
end;
 
procedure TRLEncodedHelper.Encode(Data: string);
var
pivot: Char;
i, index: Integer;
begin
Clear;
if Data.Length = 0 then
exit;
 
pivot := Data[1];
index := Add(pivot);
 
for i := 2 to Data.Length do
begin
if pivot = Data[i] then
inc(self[index].count)
else
begin
pivot := Data[i];
index := Add(pivot);
end;
end;
end;
 
function TRLEncodedHelper.ToString: string;
var
p: TRLEPair;
begin
Result := '';
for p in Self do
Result := Result + p.count.ToString + p.letter;
end;
 
const
Input = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW';
 
var
Data: TRLEncoded;
 
begin
Data.Encode(Input);
Writeln(Data.ToString);
writeln(Data.Decode);
Readln;
end.</syntaxhighlight>
{{out}}
<pre>
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|E}}==
 
<langsyntaxhighlight lang="e">def rle(string) {
var seen := null
var count := 0
Line 1,004 ⟶ 2,298:
}
return result
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="e">? rle("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
# value: [[12, 'W'], [1, 'B'], [12, 'W'], [3, 'B'], [24, 'W'], [1, 'B'], [14, 'W']]
 
? unrle(rle("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"))
# value: "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"</langsyntaxhighlight>
 
=={{header|EasyLang}}==
 
<syntaxhighlight lang="easylang">
func$ rlenc in$ .
for c$ in strchars in$
if c$ = c0$
cnt += 1
else
if cnt > 0
out$ &= cnt & c0$ & " "
.
c0$ = c$
cnt = 1
.
.
out$ &= cnt & c0$
return out$
.
func$ rldec in$ .
for h$ in strsplit in$ " "
c$ = substr h$ len h$ 1
for i to number h$
out$ &= c$
.
.
return out$
.
s$ = input
print s$
s$ = rlenc s$
print s$
s$ = rldec s$
print s$
#
input_data
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
 
</syntaxhighlight>
 
=={{header|Elena}}==
ELENA 6.x :
<syntaxhighlight lang="elena">import system'text;
import system'routines;
import extensions;
import extensions'text;
singleton compressor
{
string compress(string s)
{
auto tb := new TextBuilder();
int count := 0;
char current := s[0];
s.forEach::(ch)
{
if (ch == current)
{
count += 1
}
else
{
tb.writeFormatted("{0}{1}",count,current);
count := 1;
current := ch
}
};
tb.writeFormatted("{0}{1}",count,current);
^ tb
}
string decompress(string s)
{
auto tb := new TextBuilder();
char current := $0;
var a := new StringWriter();
s.forEach::(ch)
{
current := ch;
if (current.isDigit())
{
a.append(ch)
}
else
{
int count := a.toInt();
a.clear();
tb.fill(current,count)
}
};
^ tb
}
}
public program()
{
var s := "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
s := compressor.compress(s);
console.printLine(s);
s := compressor.decompress(s);
console.printLine(s)
}</syntaxhighlight>
{{out}}
<pre>
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|Elixir}}==
<syntaxhighlight lang="elixir">defmodule Run_length do
def encode(str) when is_bitstring(str) do
to_char_list(str) |> encode |> to_string
end
def encode(list) when is_list(list) do
Enum.chunk_by(list, &(&1))
|> Enum.flat_map(fn chars -> to_char_list(length(chars)) ++ [hd(chars)] end)
end
def decode(str) when is_bitstring(str) do
Regex.scan(~r/(\d+)(.)/, str)
|> Enum.map_join(fn [_,n,c] -> String.duplicate(c, String.to_integer(n)) end)
end
def decode(list) when is_list(list) do
to_string(list) |> decode |> to_char_list
end
end
 
text = [ string: "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW",
char_list: 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW' ]
 
Enum.each(text, fn {type, txt} ->
IO.puts type
txt |> IO.inspect
|> Run_length.encode |> IO.inspect
|> Run_length.decode |> IO.inspect
end)</syntaxhighlight>
 
{{out}}
<pre>
string
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
"12W1B12W3B24W1B14W"
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
char_list
'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
'12W1B12W3B24W1B14W'
'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'</pre>
 
=={{header|Emacs Lisp}}==
<syntaxhighlight lang="lisp">(defun run-length-encode (str)
(let (output)
(with-temp-buffer
(insert str)
(goto-char (point-min))
(while (not (eobp))
(let* ((char (char-after (point)))
(count (skip-chars-forward (string char))))
(push (format "%d%c" count char) output))))
(mapconcat #'identity (nreverse output) "")))</syntaxhighlight>
 
{{libheader|seq.el}}
<syntaxhighlight lang="lisp">(require 'seq)
 
(defun run-length-encode (str)
(let ((grouped (mapcar #'cdr (seq-group-by #'identity (string-to-list str)))))
(apply #'concat (mapcar (lambda (items)
(format "%d%c" (length items) (car items)))
grouped))))</syntaxhighlight>
 
=={{header|Erlang}}==
Line 1,016 ⟶ 2,484:
A single-threaded/process version with a simple set of unit test.
 
<langsyntaxhighlight lang="erlang">-module(rle).
 
-export([encode/1,decode/1]).
Line 1,061 ⟶ 2,529:
?_assert(decode(Expected) =:= PreEncoded),
?_assert(decode(encode(PreEncoded)) =:= PreEncoded)
].</langsyntaxhighlight>
 
A version that works on character lists:
 
<syntaxhighlight lang="erlang">
-module(rle).
 
-export([encode/1, decode/1]).
 
encode(L) -> encode(L, []).
encode([], Acc) -> {rle, lists:reverse(Acc)};
encode([H|T], []) ->
encode(T, [{1, H}]);
encode([H|T], [{Count, Char}|AT]) ->
if
H =:= Char ->
encode(T, [{Count + 1, Char}|AT]);
true ->
encode(T, [{1, H}|[{Count, Char}|AT]])
end.
 
decode({rle, L}) -> lists:append(lists:reverse(decode(L, []))).
decode([], Acc) -> Acc;
decode([{Count, Char}|T], Acc) ->
decode(T, [[Char || _ <- lists:seq(1, Count)]|Acc]).
</syntaxhighlight>
 
=={{header|Euphoria}}==
<langsyntaxhighlight lang="euphoria">include misc.e
 
function encode(sequence s)
Line 1,101 ⟶ 2,594:
pretty_print(1,s,{3})
puts(1,'\n')
puts(1,decode(s))</langsyntaxhighlight>
 
Output:
Line 1,108 ⟶ 2,601:
 
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
open System
open System.Text.RegularExpressions
Line 1,127 ⟶ 2,620:
|> List.map (fun m -> Int32.Parse(m.Groups.[1].Value), m.Groups.[2].Value)
|> List.fold (fun acc (len, s) -> acc + String.replicate len s) ""
</syntaxhighlight>
</lang>
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: io kernel literals math.parser math.ranges sequences
sequences.extras sequences.repeating splitting.extras
splitting.monotonic strings ;
IN: rosetta-code.run-length-encoding
 
CONSTANT: alpha $[ CHAR: A CHAR: Z [a,b] >string ]
 
: encode ( str -- str )
[ = ] monotonic-split [ [ length number>string ] [ first ]
bi suffix ] map concat ;
: decode ( str -- str )
alpha split* [ odd-indices ] [ even-indices
[ string>number ] map ] bi [ repeat ] 2map concat ;
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
"12W1B12W3B24W1B14W"
[ encode ] [ decode ] bi* [ print ] bi@</syntaxhighlight>
{{out}}
<pre>
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|FALSE}}==
<langsyntaxhighlight lang="false">1^[^$~][$@$@=$[%%\1+\$0~]?~[@.,1\$]?%]#%\., {encode}</langsyntaxhighlight>
<langsyntaxhighlight lang="false">[0[^$$'9>'0@>|~]['0-\10*+]#]n:
[n;!$~][[\$][1-\$,]#%%]#%% {decode}</langsyntaxhighlight>
 
=={{header|Fan}}==
<syntaxhighlight lang="fan">**
<lang Fan>**
** Generates a run-length encoding for a string
**
Line 1,181 ⟶ 2,699:
 
override Str toStr() { return "${count}${char.toChar}" }
}</langsyntaxhighlight>
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">variable a
: n>a (.) tuck a @ swap move a +! ;
: >a a @ c! 1 a +! ;
Line 1,198 ⟶ 2,716:
i c@ digit? if 10 * i c@ [char] 0 - + else
a @ over i c@ fill a +! 0 then
loop drop a @ over - ;</langsyntaxhighlight>
 
Example:
 
<langsyntaxhighlight lang="forth">s" WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
here 1000 + encode here 2000 + decode cr 3 spaces type
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</langsyntaxhighlight>
 
=={{header|Fortran}}==
{{works with|Fortran|95 and later}}
<langsyntaxhighlight lang="fortran">program RLE
implicit none
 
integer, parameter :: bufsize = 100 ! Sets maximum size of coded and decoded strings, adjust as necessary
character(bufsize) :: teststr = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
character(bufsize) :: codedstr = "", Encodedecodedstr (Data= (Index..Data'Last));""
end;
end;
end if;
end Encode;
function Decode (Data : String) return String is
begin
if Data'Length = 0 then
return "";
else
declare
Index : Integer := Data'First;
Count : Natural := 0;
begin
while Index , decodedstr = ""
call Encode(teststr, codedstr)
Line 1,280 ⟶ 2,784:
end do
end subroutine
end program</langsyntaxhighlight>
 
Output:
<pre>
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">
Dim As String initial, encoded, decoded
 
Function RLDecode(i As String) As String
Dim As Long Loop0
dim as string rCount, outP, m
For Loop0 = 1 To Len(i)
m = Mid(i, Loop0, 1)
Select Case m
Case "0" To "9"
rCount += m
Case Else
If Len(rCount) Then
outP += String(Val(rCount), m)
rCount = ""
Else
outP += m
End If
End Select
Next
RLDecode = outP
End Function
 
Function RLEncode(i As String) As String
Dim As String tmp1, tmp2, outP
Dim As Long Loop0, rCount
tmp1 = Mid(i, 1, 1)
tmp2 = tmp1
rCount = 1
For Loop0 = 2 To Len(i)
tmp1 = Mid(i, Loop0, 1)
If tmp1 <> tmp2 Then
outP += Ltrim(Rtrim(Str(rCount))) + tmp2
tmp2 = tmp1
rCount = 1
Else
rCount += 1
End If
Next
outP += Ltrim(Rtrim(Str(rCount)))
outP += tmp2
RLEncode = outP
End Function
 
Input "Type something: ", initial
encoded = RLEncode(initial)
decoded = RLDecode(encoded)
Print initial
Print encoded
Print decoded
End
</syntaxhighlight>
{{out}}
La salida es similar a la de [[#BASIC|BASIC]], mostrada arriba.
 
=={{header|FutureBasic}}==
This gives RLE encoding for strings and RLE decoding for strings and arrays, e.g., for [[Conway's_Game_of_Life|Conway's Game of Life]]
<syntaxhighlight lang=FutureBasic>
 
local fn encode( string as CFStringRef) as CFStringRef
CFStringRef ch, s, t
Short i, rl
s = @"" // Initalize the output string
for i = 0 to len( string ) - 1 // Encode string char by char
ch = mid( string, i, 1) // Read character at index
rl = 1 // Start run-length counter
while fn StringIsEqual( mid( string, i + rl, 1), ch )
rl ++ // Same char, so increase counter
wend
if rl == 1 then t = @"" else t = fn StringWithFormat( @"%d", rl ) // Counter as string, don't encode 1's
t = fn StringByAppendingString( t, ch ) // Add character
s = fn StringByAppendingString( s, t ) // Add to already encoded string
i += rl - 1 // Move index
next
print s
end fn
 
 
local fn decode( string as CFStringRef )
CFStringRef ch, s, t // character, outputstring, temporary string
Short i, rl // index, run length
s = @"" // Initalize the output string
for i = 0 to len( string ) - 1 // Decode input string char by char
ch = mid( string, i, 1 ) // Read character at index
if intval( ch ) == 0 // Not a digit
rl = 1
else
rl = intval( mid( string, i ) ) // Read run-length
i += fix( log10( rl ) + 1 ) // Move index past digits
ch = mid( string, i, 1 ) // Read character after run length
end if
t = fn StringByPaddingToLength( ch, rl, ch, 0 ) // Assemble temp string
s = fn StringByAppendingString( s, t ) // Add to decoded string
next
print s
end fn
 
 
local fn decode2D( string as CFStringRef ) // For Conway's Game of Life objects
Boolean a(500, 500) // Or larger to hold bigger life forms
CFStringRef ch
Short i, j, rl, f // Decoded char
Short v = 0, w = 0, x = 0, y = 0 // Temp width, max width, array coordinates
for i = 0 to len( string ) - 2 // Final char is always !
ch = mid( string, i, 1 )
if intval( ch ) == 0
rl = 1
else
rl = intval( mid( string, i ) )
i += fix( log10( rl ) + 1 )
ch = mid( string, i, 1 )
end if
select ch // Decode character as:
case @"$" : f = -1 // - new line
case @"b" : f = 0 // - dead
case @"o" : f = 1 // - live
case else : // Ignore
end select
for j = 1 to rl // Fill array with run of chars
if f = -1
x = 0 : y ++ : v = 0 // New line
else
a(x, y) = f
x ++ : v ++ : if v > w then w = v
end if
next
next
for j = 0 to y : for i = 0 to w - 1
print a(i, j);
next : print : next
end fn
 
fn decode( @"12W1B12W3B24W1B14W" ) // Assignment
fn encode( @"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" )
fn decode2D( @"bo$2bo$3o!" ) // Glider
 
handleevents // Join Mac event loop
 
</syntaxhighlight>
Output:
<pre>
 
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
12WB12W3B24WB14W
011
001
111
 
</pre>
 
=={{header|Gambas}}==
'''[https://gambas-playground.proko.eu/?gist=b30707043cb64effba91a2edc4d4be94 Click this link to run this code]'''
<syntaxhighlight lang="gambas">Public Sub Main()
Dim sString As String = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
Dim siCount As Short = 1
Dim siStart As Short = 1
Dim sHold As New String[]
Dim sTemp As String
 
sString &= " "
 
Repeat
sTemp = Mid(sString, siCount, 1)
Do
Inc siCount
If Mid(sString, siCount, 1) <> sTemp Then Break
If siCount = Len(sString) Then Break
Loop
sHold.add(Str(siCount - siStart) & sTemp)
siStart = siCount
Until siCount = Len(sString)
 
Print sString & gb.NewLine & sHold.Join(", ")
 
End</syntaxhighlight>
Output:
<pre>
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
12W, 1B, 12W, 3B, 24W, 1B, 14W
</pre>
 
=={{header|Go}}==
Decoder kind of necessary to demonstrate task requirement that I can recreate the input.
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,353 ⟶ 3,050:
}
return string(d)
}</langsyntaxhighlight>
Output:
<pre>
Line 1,363 ⟶ 3,060:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def rleEncode(text) {
def encoded = new StringBuilder()
(text =~ /(([A-Z])\2*)/).each { matcher ->
Line 1,377 ⟶ 3,074:
}
decoded.toString()
}</langsyntaxhighlight>
Test code
<langsyntaxhighlight lang="groovy">def text = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
def rleEncoded = rleEncode(text)
assert rleEncoded == '12W1B12W3B24W1B14W'
Line 1,385 ⟶ 3,082:
 
println "Original Text: $text"
println "Encoded Text: $rleEncoded"</langsyntaxhighlight>
Output:
<pre>Original Text: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 1,391 ⟶ 3,088:
 
=={{header|Haskell}}==
===In terms of group===
<lang haskell>import Data.List (group)
<syntaxhighlight lang="haskell">import Data.List (group)
 
-- Datatypes
type Encoded = [(Int, Char)] -- An encoded String with form [(times, char), ...]
 
type Decoded = String
 
-- Takes a decoded string and returns an encoded list of tuples
rlencode :: Decoded -> Encoded
rlencode = mapfmap (\g(,) -<$> (length g,<*> head g)) . group
 
-- Takes an encoded list of tuples and returns the associated decoded String
rldecode :: Encoded -> Decoded
rldecode = concatMap decodeTuple(uncurry replicate)
where decodeTuple (n,c) = replicate n c
 
main :: IO ()
main = do
let input = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
-- Get input
-- Output encoded and decoded versions of input
putStr "String to encode: "
encoded = rlencode input
input <- getLine
-- Output encoded and decoded versions of input
let encoded = rlencode input
decoded = rldecode encoded
putStrLn $ "Encoded: " ++<> show encoded ++<> "\nDecoded: " ++<> show decoded</langsyntaxhighlight>
{{Out}}
<pre>Encoded: [(12,'W'),(1,'B'),(12,'W'),(3,'B'),(24,'W'),(1,'B'),(14,'W')]
Decoded: "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"</pre>
 
Or:
<syntaxhighlight lang="haskell">import Data.Char (isDigit)
import Data.List (group, groupBy)
 
runLengthEncode :: String -> String
runLengthEncode =
concatMap
( \xs@(x : _) ->
( show . length $ xs
)
<> [x]
)
. group
 
runLengthDecode :: String -> String
runLengthDecode =
concat . uncurry (zipWith (\[x] ns -> replicate (read ns) x))
. foldr (\z (x, y) -> (y, z : x)) ([], [])
. groupBy (\x y -> all isDigit [x, y])
 
main :: IO ()
main = do
let text = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
encode = runLengthEncode text
decode = runLengthDecode encode
mapM_ putStrLn [text, encode, decode]
putStrLn $ "test: text == decode => " <> show (text == decode)</syntaxhighlight>
{{out}}
<pre>WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
test: text == decode => True</pre>
 
===In terms of span===
<syntaxhighlight lang="haskell">import Data.Char (isDigit)
import Data.List (span)
 
encode :: String -> String
encode [] = []
encode (x : xs) =
let (run, rest) = span (x ==) xs
in x : (show . succ . length) run <> encode rest
 
decode :: String -> String
decode [] = []
decode (x : xs) =
let (ds, rest) = span isDigit xs
n = read ds :: Int
in replicate n x <> decode rest
 
main :: IO ()
main =
putStrLn encoded
>> putStrLn decoded
>> print (src == decoded)
where
src = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
encoded = encode src
decoded = decode encoded</syntaxhighlight>
{{Out}}
<pre>W12B1W12B3W24B1W14
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
True</pre>
 
===As a fold===
<syntaxhighlight lang="haskell">----------------------- RUN LENGTHS ----------------------
 
runLengths :: String -> [(Int, Char)]
runLengths "" = []
runLengths s = uncurry (:) (foldr go ((0, ' '), []) s)
where
go c ((0, _), xs) = ((1, c), xs)
go c ((n, x), xs)
| c == x = ((succ n, x), xs)
| otherwise = ((1, c), (n, x) : xs)
 
--------------------------- TEST -------------------------
main :: IO ()
main = do
let testString =
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWW"
<> "WWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
encoded = runLengths testString
putStrLn $ showLengths encoded
print $
concatMap (uncurry replicate) encoded == testString
 
------------------------- DISPLAY ------------------------
showLengths :: [(Int, Char)] -> String
showLengths [] = []
showLengths ((n, c) : xs) = show n <> [c] <> showLengths xs</syntaxhighlight>
{{Out}}
<pre>12W1B12W3B24W1B14W
True</pre>
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">procedure main(arglist)
 
s := "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
Line 1,443 ⟶ 3,237:
procedure Repl(n, c)
return repl(c,n)
end</langsyntaxhighlight>
 
Sample output:
Line 1,453 ⟶ 3,247:
=={{header|J}}==
'''Solution:'''
<langsyntaxhighlight lang="j">rle=: ;@(<@(":@(#-.1:),{.);.1~ 1, 2 ~:/\ ])
rld=: '0123456789'&;@(-.~@e.&'0123456789' <@({:#~ i1{. @,~".@}:{ ' ' ,~);.2 [])</langsyntaxhighlight>
 
'''Example:'''
<langsyntaxhighlight lang="j"> rle 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
12W1B12W3B24W1B14W
 
rld '12W1B12W3B24W1B14W'
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</langsyntaxhighlight>
 
Note that this implementation fails for the empty case. Here's a version that fixes that:
 
<langsyntaxhighlight lang="j">rle=: ;@(<@(":@#,{.);.1~ 2 ~:/\ (a.{.@-.{.),])</langsyntaxhighlight>
 
Other approaches include using <nowiki>rle ::(''"_)</nowiki> or <nowiki>rle^:(*@#)</nowiki> or equivalent variations on the original sentence.
 
=== Alternative Implementation ===
 
A numeric approach, based on a discussion in the J forums (primarily [http://jsoftware.com/pipermail/programming/2015-June/042139.html Pascal Jasmin] and [http://jsoftware.com/pipermail/programming/2015-June/042141.html Marshall Lochbaum]):
 
<syntaxhighlight lang="j"> torle=: (#, {.);.1~ 1,2 ~:/\ ]
frle=: #/@|:</syntaxhighlight>
 
Task example:
 
<syntaxhighlight lang="j"> torle a.i.'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
12 87
1 66
12 87
3 66
24 87
1 66
14 87
u: frle torle a.i.'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</syntaxhighlight>
 
Note that this approach also fails on the empty case.
 
=={{header|Java}}==
This can be achieved using regular expression capturing
<lang java>import java.util.regex.Matcher;
<syntaxhighlight lang="java">
import java.util.regex.Matcher;
import java.util.regex.Pattern;
</syntaxhighlight>
<syntaxhighlight lang="java">
String encode(String string) {
Pattern pattern = Pattern.compile("(.)\\1*");
Matcher matcher = pattern.matcher(string);
StringBuilder encoded = new StringBuilder();
while (matcher.find()) {
encoded.append(matcher.group().length());
encoded.append(matcher.group().charAt(0));
}
return encoded.toString();
}
</syntaxhighlight>
<syntaxhighlight lang="java">
String decode(String string) {
Pattern pattern = Pattern.compile("(\\d+)(.)");
Matcher matcher = pattern.matcher(string);
StringBuilder decoded = new StringBuilder();
int count;
while (matcher.find()) {
count = Integer.parseInt(matcher.group(1));
decoded.append(matcher.group(2).repeat(count));
}
return decoded.toString();
}
</syntaxhighlight>
<pre>
string = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
encoded = 12W1B12W3B24W1B14W
decoded = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
string.equals(decoded) = true
 
string = https://www.rosettacode.org/
encoded = 1h2t1p1s1:2/3w1.1r1o1s1e2t1a1c1o1d1e1.1o1r1g1/
decoded = https://www.rosettacode.org/
string.equals(decoded) = true
</pre>
<br />
An alternate demonstration
<syntaxhighlight lang="java">import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RunLengthEncoding {
Line 1,507 ⟶ 3,366:
System.out.println(decode("1W1B1W1B1W1B1W1B1W1B1W1B1W1B"));
}
}</langsyntaxhighlight>
Tests:
 
{{libheader|JUnit}}
<langsyntaxhighlight lang="java">import static org.junit.Assert.assertEquals;
 
import org.junit.Test;
Line 1,542 ⟶ 3,401:
 
}
}</langsyntaxhighlight>
 
=={{header|JavaScript}}==
===ES5===
Here's an encoding method that walks the input string character by character
<langsyntaxhighlight lang="javascript">function encode(input) {
var encoding = [];
var prev, count, i;
Line 1,560 ⟶ 3,420:
encoding.push([count, prev]);
return encoding;
}</langsyntaxhighlight>
 
Here's an encoding method that uses a regular expression to grab the character runs ({{works with|JavaScript|1.6}} for the <code>forEach</code> method)
<langsyntaxhighlight lang="javascript">function encode_re(input) {
var encoding = [];
input.match(/(.)\1*/g).forEach(function(substr){ encoding.push([substr.length, substr[0]]) });
return encoding;
}</langsyntaxhighlight>
 
And to decode (see [[Repeating a string#JavaScript|Repeating a string]])
<langsyntaxhighlight lang="javascript">function decode(encoded) {
var output = "";
encoded.forEach(function(pair){ output += new Array(1+pair[0]).join(pair[1]) })
return output;
}</langsyntaxhighlight>
 
=={{header|K}}=ES6===
By defining a generic ''group'' function:
<syntaxhighlight lang="javascript">(() => {
'use strict';
 
// runLengthEncode :: String -> [(Int, Char)]
const runLengthEncoded = s =>
group(s.split('')).map(
cs => [cs.length, cs[0]]
);
 
// runLengthDecoded :: [(Int, Char)] -> String
<lang k>rle: {,/($-':i,#x),'x@i:&1,~=':x}</lang>
const runLengthDecoded = pairs =>
pairs.map(([n, c]) => c.repeat(n)).join('');
 
 
// ------------------------TEST------------------------
const main = () => {
const
xs = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWW' +
'WWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW',
ys = runLengthEncoded(xs);
 
console.log('From: ', show(xs));
[ys, runLengthDecoded(ys)].forEach(
x => console.log(' -> ', show(x))
)
};
 
// ----------------------GENERIC-----------------------
 
// group :: [a] -> [[a]]
const group = xs => {
// A list of lists, each containing only equal elements,
// such that the concatenation of these lists is xs.
const go = xs =>
0 < xs.length ? (() => {
const
h = xs[0],
i = xs.findIndex(x => h !== x);
return i !== -1 ? (
[xs.slice(0, i)].concat(go(xs.slice(i)))
) : [xs];
})() : [];
return go(xs);
};
 
// show :: a -> String
const show = JSON.stringify;
 
// MAIN ---
return main();
})();</syntaxhighlight>
{{Out}}
<pre>From: "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
-> [[12,"W"],[1,"B"],[12,"W"],[3,"B"],[24,"W"],[1,"B"],[14,"W"]]
-> "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"</pre>
 
A <code>.reduce()</code> based one-liner
<syntaxhighlight lang="javascript">
const rlEncode = (s: string) => s.match(/(.)\1*/g).reduce((result,char) => result+char.length+char[0],"")
const rlValidate = (s: string) => /^(\d+\D)+$/.test(s)
const rlDecode = (s: string) => rlValidate(s) ? s.match(/(\d[a-z\s])\1*/ig).reduce((res,p) => res+p[p.length-1].repeat(parseInt(p)),"") : Error("Invalid rl")
</syntaxhighlight>
 
=={{header|jq}}==
Note: "run_length_decode" as defined below requires a version of jq with regex support.
 
'''Utility function:'''
<syntaxhighlight lang="jq">def runs:
reduce .[] as $item
( [];
if . == [] then [ [ $item, 1] ]
else .[length-1] as $last
| if $last[0] == $item then .[length-1] = [$item, $last[1] + 1]
else . + [[$item, 1]]
end
end ) ;</syntaxhighlight>
'''Run-length encoding and decoding''':
<syntaxhighlight lang="jq">def run_length_encode:
explode | runs | reduce .[] as $x (""; . + "\($x[1])\([$x[0]]|implode)");
 
def run_length_decode:
reduce (scan( "[0-9]+[A-Z]" )) as $pair
( "";
($pair[0:-1] | tonumber) as $n
| $pair[-1:] as $letter
| . + ($n * $letter)) ;</syntaxhighlight>
'''Example''':
<syntaxhighlight lang="jq">"ABBCCC" | run_length_encode | run_length_decode</syntaxhighlight>
{{out}}
<syntaxhighlight lang="sh">$ jq -n -f Run_length_encoding.jq
"ABBCCC"</syntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<syntaxhighlight lang="julia">using IterTools
 
encode(str::String) = collect((length(g), first(g)) for g in groupby(first, str))
decode(cod::Vector) = join(repeat("$l", n) for (n, l) in cod)
 
for original in ["aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa", "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"]
encoded = encode(original)
decoded = decode(encoded)
println("Original: $original\n -> encoded: $encoded\n -> decoded: $decoded")
end</syntaxhighlight>
 
{{out}}
<pre>Original: aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa
-> encoded: Tuple{Int64,Char}[(5, 'a'), (6, 'h'), (7, 'm'), (1, 'u'), (7, 'i'), (6, 'a')]
-> decoded: aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa
Original: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
-> encoded: Tuple{Int64,Char}[(12, 'W'), (1, 'B'), (12, 'W'), (3, 'B'), (24, 'W'), (1, 'B'), (14, 'W')]
-> decoded: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|K}}==
 
<syntaxhighlight lang="k">rle: {,/($-':i,#x),'x@i:&1,~=':x}</syntaxhighlight>
 
{{trans|J}}
 
<langsyntaxhighlight lang="k">rld: {d:"0123456789"; ,/(.(d," ")@d?/:x)#'x _dvl d}</langsyntaxhighlight>
 
'''Example:'''
 
<langsyntaxhighlight lang="k"> rle "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
"12W1B12W3B24W1B14W"
rld "12W1B12W3B24W1B14W"
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"</langsyntaxhighlight>
 
=={{header|Kotlin}}==
Tail recursive implementation of Run Length Encoding
<syntaxhighlight lang="scala">tailrec fun runLengthEncoding(text:String,prev:String=""):String {
if (text.isEmpty()){
return prev
}
val initialChar = text.get(0)
val count = text.takeWhile{ it==initialChar }.count()
return runLengthEncoding(text.substring(count),prev + "$count$initialChar" )
}
 
fun main(args: Array<String>) {
assert(runLengthEncoding("TTESSST") == "2T1E3S1T")
assert(runLengthEncoding("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
== "12W1B12W3B24W1B14W")
}</syntaxhighlight>
 
=={{header|Lasso}}==
<syntaxhighlight lang="lasso">define rle(str::string)::string => {
local(orig = #str->values->asCopy,newi=array, newc=array, compiled=string)
while(#orig->size) => {
if(not #newi->size) => {
#newi->insert(1)
#newc->insert(#orig->first)
#orig->remove(1)
else
if(#orig->first == #newc->last) => {
#newi->get(#newi->size) += 1
else
#newi->insert(1)
#newc->insert(#orig->first)
}
#orig->remove(1)
}
}
loop(#newi->size) => {
#compiled->append(#newi->get(loop_count)+#newc->get(loop_count))
}
return #compiled
}
define rlde(str::string)::string => {
local(o = string)
while(#str->size) => {
loop(#str->size) => {
if(#str->isualphabetic(loop_count)) => {
if(loop_count == 1) => {
#o->append(#str->get(loop_count))
#str->removeLeading(#str->get(loop_count))
loop_abort
}
local(num = integer(#str->substring(1,loop_count)))
#o->append(#str->get(loop_count)*#num)
#str->removeLeading(#num+#str->get(loop_count))
loop_abort
}
}
}
return #o
}
//Tests:
rle('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW')
rle('dsfkjhhkdsjfhdskhshdjjfhhdlsllw')
 
rlde('12W1B12W3B24W1B14W')
rlde('1d1s1f1k1j2h1k1d1s1j1f1h1d1s1k1h1s1h1d2j1f2h1d1l1s2l1w')</syntaxhighlight>
 
{{out}}
<pre>12W1B12W3B24W1B14W
1d1s1f1k1j2h1k1d1s1j1f1h1d1s1k1h1s1h1d2j1f2h1d1l1s2l1w
 
 
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
dsfkjhhkdsjfhdskhshdjjfhhdlsllw</pre>
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">mainwin 100 20
 
'In$ ="aaaaaaaaaaaaaaaaaccbbbbbbbbbbbbbbba" ' testing...
Line 1,640 ⟶ 3,689:
next i
Decoded$ =r$
end function</langsyntaxhighlight>
 
=={{header|LiveCode}}==
<syntaxhighlight lang="livecode">function rlEncode str
local charCount
put 1 into charCount
repeat with i = 1 to the length of str
if char i of str = char (i + 1) of str then
add 1 to charCount
else
put char i of str & charCount after rle
put 1 into charCount
end if
end repeat
return rle
end rlEncode
 
function rlDecode str
repeat with i = 1 to the length of str
if char i of str is not a number then
put char i of str into curChar
put 0 into curNum
else
repeat with n = i to len(str)
if isnumber(char n of str) then
put char n of str after curNum
else
put repeatString(curChar,curNum) after rldec
put n - 1 into i
exit repeat
end if
end repeat
end if
if i = len(str) then --dump last char
put repeatString(curChar,curNum) after rldec
end if
end repeat
return rldec
end rlDecode
 
function repeatString str,rep
repeat rep times
put str after repStr
end repeat
return repStr
end repeatString</syntaxhighlight>
 
=={{header|Logo}}==
<langsyntaxhighlight lang="logo">to encode :str [:out "||] [:count 0] [:last first :str]
if empty? :str [output (word :out :count :last)]
if equal? first :str :last [output (encode bf :str :out :count+1 :last)]
Line 1,660 ⟶ 3,754:
make "foo "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
make "rle encode :foo
show equal? :foo decode :rle</langsyntaxhighlight>
 
=={{header|Lua}}==
 
<langsyntaxhighlight lang="lua">local C, Ct, R, Cf, Cc = lpeg.C, lpeg.Ct, lpeg.R, lpeg.Cf, lpeg.Cc
astable = Ct(C(1)^0)
 
Line 1,694 ⟶ 3,788:
end
return ret
end</langsyntaxhighlight>
 
=={{header|MathematicaM2000 Interpreter}}==
<syntaxhighlight lang="m2000 interpreter">
Custom functions using Map, Apply, pure functions, replacing using pattern matching, delayed rules and other functions:
Module RLE_example {
<lang Mathematica>RunLengthEncode[input_String]:=StringJoin@@Sequence@@@({ToString @Length[#],First[#]}&/@Split[Characters[input]])
inp$="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
RunLengthDecode[input_String]:=StringJoin@@ConstantArray@@@Reverse/@Partition[(Characters[input]/.(ToString[#]->#&/@Range[0,9]))//.{x___,i_Integer,j_Integer,y___}:>{x,10i+j,y},2]</lang>
Print "Input: ";inp$
Example:
Function RLE$(r$){
<lang Mathematica>mystring="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
Function rle_run$(&r$) {
RunLengthEncode[mystring]
if len(r$)=0 then exit
RunLengthDecode[%]
p=1
%==mystring</lang>
c$=left$(r$,1)
gives back:
while c$=mid$(r$, p, 1) {p++}
<lang Mathematica>12W1B12W3B24W1B14W
=format$("{0}{1}",p-1, c$)
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
r$=mid$(r$, p)
True</lang>
}
An alternate solution:
def repl$
<lang Mathematica>RunLengthEncode[s_String] := StringJoin[
while len(r$)>0 {repl$+=rle_run$(&r$)}
{ToString[Length[#]] <> First[#]} & /@ Split[StringSplit[s, ""]]
=repl$
]
}
RLE_encode$=RLE$(inp$)
Print "RLE Encoded: ";RLE_encode$
Function RLE_decode$(r$) {
def repl$
def long m, many=1
while r$<>"" and many>0 {
many=val(r$, "INT", &m)
repl$+=string$(mid$(r$, m, 1), many)
r$=mid$(r$,m+1)
}
=repl$
}
RLE_decode$=RLE_decode$(RLE_encode$)
Print "RLE Decoded: ";RLE_decode$
Print "Checked: ";RLE_decode$=inp$
}
RLE_example
</syntaxhighlight>
 
{{out}}
<pre style="height:30ex;overflow:scroll">
Input: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
RLE Encoded: 12W1B12W3B24W1B14W
RLE Decoded: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Checked: True
</pre >
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
The function
 
<syntaxhighlight lang="mathematica">RunLengthEncode[input_String]:= (l |-> {First@l, Length@l}) /@ (Split@Characters@input)</syntaxhighlight>
 
takes as input an arbitrary string of characters and returns a list of {c, n} pairs, where c is the character and n is the number of repeats. The function
 
<syntaxhighlight lang="mathematica">RunLengthDecode[input_List]:= ConstantArray @@@ input // Flatten // StringJoin</syntaxhighlight>
 
recreates the string.
 
Example: For the string
 
<syntaxhighlight lang="mathematica">mystring="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";</syntaxhighlight>
 
here is the run-length encoding:
 
<syntaxhighlight lang="mathematica">rle = RunLengthEncode[mystring]
 
{{"W", 12}, {"B", 1}, {"W", 12}, {"B", 3}, {"W", 24}, {"B", 1}, {"W", 14}}</syntaxhighlight>
 
Check that the input string is recreated:
 
<syntaxhighlight lang="mathematica">mystring == RunLengthDecode[rle]
 
True</syntaxhighlight>
RunLengthDecode[s_String] := StringJoin[
Table[#[[2]], {ToExpression[#[[1]]]}] & /@
Partition[StringSplit[s, x : _?LetterQ :> x], 2]
]</lang>
This second encode function is adapted from the MathWorld example.
 
=={{header|Maxima}}==
To encode
<lang maxima>rle(a) := block(
<syntaxhighlight lang="maxima">rle(a) := block(
[n: slength(a), b: "", c: charat(a, 1), k: 1],
for i from 2 thru n do
Line 1,727 ⟶ 3,870:
sconcat(b, k, c)
)$
</syntaxhighlight>
To decode
<syntaxhighlight lang="maxima">
 
/* Function to return a list where all but the last entries are integers */
intbucket(lst):=block(bucket:[],while integerp(first(lst)) do (push(first(lst),bucket),lst:rest(lst)),lst:append(reverse(bucket),[first(lst)]));
 
/* Run-length decoding */
rld(string_list):=block(
coref:map(eval_string,charlist(string_list)),
listcharact:sublist(coref,lambda([x],integerp(x)=false)),
map(intbucket,append([coref],makelist(coref:rest(coref,length(intbucket(coref))),length(listcharact)-1))),
makelist(sublist(%%[i],integerp),i,1,length(%%)),
map(eval_string,makelist(apply(concat,%%[i]),i,1,length(%%))),
makelist(smake(%%[i],string(listcharact[i])),i,1,length(listcharact)),
apply(concat,%%));
</syntaxhighlight>
 
Output
<syntaxhighlight lang="maxima">
rle("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW");
"12W1B12W3B24W1B14W"</lang>
rld(%);
/* "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" */
</syntaxhighlight>
 
=={{header|MMIX}}==
<langsyntaxhighlight lang="mmix"> LOC Data_Segment
GREG @
Buf OCTA 0,0,0,0 integer print buffer
Line 1,841 ⟶ 4,006:
2H SET $4,#a print NL
GO $127,PChar
TRAP 0,Halt,0 EXIT</langsyntaxhighlight>
Example run encode --> decode:
<pre>~/MIX/MMIX/Rosetta> mmix rle
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|Nim}}==
{{trans|Python}}
<syntaxhighlight lang="nim">import parseutils, strutils
 
proc compress(input: string): string =
var
count = 1
prev = '\0'
 
for ch in input:
if ch != prev:
if prev != '\0':
result.add $count & prev
count = 1
prev = ch
else:
inc count
result.add $count & prev
 
proc uncompress(text: string): string =
var start = 0
var count: int
while true:
let n = text.parseInt(count, start)
if n == 0 or start + n >= text.len:
raise newException(ValueError, "corrupted data.")
inc start, n
result.add repeat(text[start], count)
inc start
if start == text.len: break
 
 
const Text = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
 
echo "Text: ", Text
let compressed = Text.compress()
echo "Compressed: ", compressed
echo "Uncompressed: ", compressed.uncompress()</syntaxhighlight>
 
{{out}}
<pre>Text: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Compressed: 12W1B12W3B24W1B14W
Uncompressed: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|Objeck}}==
<syntaxhighlight lang="objeck">use RegEx;
 
class RunLengthEncoding {
function : Main(args : String[]) ~ Nil {
input := "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
encoded := Encode(input);
"encoding: {$encoded}"->PrintLine();
test := encoded->Equals("12W1B12W3B24W1B14W");
"encoding match: {$test}"->PrintLine();
decoded := Decode(encoded);
test := input->Equals(decoded);
"decoding match: {$test}"->PrintLine();
}
function : Encode(source : String) ~ String {
dest := "";
each(i : source) {
runLength := 1;
while(i+1 < source->Size() & source->Get(i) = source->Get(i+1)) {
runLength+= 1;
i+= 1;
};
dest->Append(runLength);
dest->Append(source->Get(i));
};
 
return dest;
}
 
function : Decode(source : String) ~ String {
output := "";
regex := RegEx->New("[0-9]+|([A-Z]|[a-z])");
found := regex->Find(source);
count : Int;
each(i : found) {
if(i % 2 = 0) {
count := found->Get(i)->As(String)->ToInt();
}
else {
letter := found->Get(i)->As(String);
while(count <> 0) {
output->Append(letter);
count -= 1;
};
};
};
return output;
}
}</syntaxhighlight>
 
<pre>encoding: 12W1B12W3B24W1B14W
encoding match: true
decoding match: true</pre>
 
=={{header|Objective-C}}==
Line 1,851 ⟶ 4,118:
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">let encode str =
let len = String.length str in
let rec aux i acc =
Line 1,873 ⟶ 4,140:
let decode lst =
let l = List.map (fun (c,n) -> String.make n c) lst in
(String.concat "" l)</langsyntaxhighlight>
 
<langsyntaxhighlight lang="ocaml">let () =
let e = encode "aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa" in
List.iter (fun (c,n) ->
Line 1,881 ⟶ 4,148:
) e;
print_endline (decode [('a', 5); ('h', 6); ('m', 7); ('u', 1); ('i', 7); ('a', 6)]);
;;</langsyntaxhighlight>
 
;Using regular expressions
<langsyntaxhighlight lang="ocaml">#load "str.cma";;
 
open Str
Line 1,900 ⟶ 4,167:
let () =
print_endline (encode "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW");
print_endline (decode "12W1B12W3B24W1B14W");</langsyntaxhighlight>
 
=={{header|Oforth}}==
 
<syntaxhighlight lang="oforth">: encode(s)
StringBuffer new
s group apply(#[ tuck size asString << swap first <<c ]) ;
 
: decode(s)
| c i |
StringBuffer new
0 s forEach: c [
c isDigit ifTrue: [ 10 * c asDigit + continue ]
loop: i [ c <<c ] 0
]
drop ;</syntaxhighlight>
 
{{out}}
<pre>
>"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" encode .s
[1] (StringBuffer) 12W1B12W3B24W1B14W
ok
>decode .s
[1] (StringBuffer) WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
ok
</pre>
 
=={{header|Ol}}==
<syntaxhighlight lang="scheme">
(define (RLE str)
(define iter (string->list str))
(let loop ((iter iter) (chr (car iter)) (n 0) (rle '()))
(cond
((null? iter)
(reverse (cons (cons n chr) rle)))
((char=? chr (car iter))
(loop (cdr iter) chr (+ n 1) rle))
(else
(loop (cdr iter) (car iter) 1 (cons (cons n chr) rle))))))
 
(define (decode rle)
(apply string-append (map (lambda (p)
(make-string (car p) (cdr p))) rle)))
</syntaxhighlight>
Test:
<syntaxhighlight lang="scheme">
(define str "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
(print str)
 
(define rle (RLE str))
(for-each (lambda (pair)
(print (car pair) " : " (string (cdr pair))))
rle)
(print (decode rle))
</syntaxhighlight>
{{Out}}
<pre>
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
12 : W
1 : B
12 : W
3 : B
24 : W
1 : B
14 : W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
=={{header|Oz}}==
<langsyntaxhighlight lang="oz">declare
fun {RLEncode Xs}
for G in {Group Xs} collect:C do
Line 1,939 ⟶ 4,271:
{System.showInfo Data}
{Show Enc}
{System.showInfo {RLDecode Enc}}</langsyntaxhighlight>
 
=={{header|PARI/GP}}==
<langsyntaxhighlight lang="parigp">rle(s)={
if(s=="", return(s));
my(v=Vec(s),cur=v[1],ct=1,out="");
Line 1,971 ⟶ 4,304:
};
rle("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
elr(%)</langsyntaxhighlight>
Output:
<pre>%1 = "12W1B12W3B24W1B14W"
Line 1,978 ⟶ 4,311:
 
=={{header|Pascal}}==
<langsyntaxhighlight lang="pascal">Program RunLengthEncoding(output);
procedure encode(s: string; var counts: array of integer; var letters: string);
Line 2,028 ⟶ 4,361:
decode(s, counts, letters);
writeln(s);
end.</langsyntaxhighlight>
Output:
<pre>:> ./RunLengthEncoding
Line 2,037 ⟶ 4,370:
 
=={{header|Perl}}==
<lang perl>
# functional approach (return the encoded or decoded string)
sub encode {
(my $str = shift) =~ s {(.)(\1*)} {length($&).$1}gse;
return $str; }
sub decode {
(my $str = shift) =~ s {(\d+)(.)} {$2 x $1}gse;
return $str;}
 
Simple version using ASCII numerals as length markers, like the example in the task description (won't work correctly on input strings that already contain digits):
# procedural approach (modify the argument in place)
 
sub encode {
<syntaxhighlight lang="perl">sub encode {
$_[0] =~ s {(.)(\1*)} {length($&).$1}gse; }
shift =~ s/(.)\1*/length($&).$1/grse;
}
 
sub decode {
$_[0] shift =~ s {/(\d+)(.)} {/$2 x $1}gse/grse; }
}</syntaxhighlight>
</lang>
 
TheModified followingversion modifiedthat versionscan oftake thearbitrary previousbyte one,strings encode/decodeas ainput bytes(produces sequenceencoded inbyte astrings waythat are compatible with the functions of the [[Run-length encoding#C|C versionsolution]].):
 
<langsyntaxhighlight lang="perl">sub encode {
shift =~ s/(.)\1{0,254}/pack("C", length($&)).$1/grse;
{my $str = shift;
}
$str =~ s {(.)(\1{0,254})} {pack("C",(length($2) + 1)) . $1 }gse;
return $str;}
sub decode
{
my @str = split //, shift;
my $r = "";
foreach my $i (0 .. scalar(@str)/2-1) {
$r .= $str[2*$i + 1] x unpack("C", $str[2*$i]);
}
return $r;
}</lang>
 
sub decode {
=={{header|Perl 6}}==
shift =~ s/(.)(.)/$2 x unpack("C", $1)/grse;
This currently depend on a workaround to pass the match object into the replacement closure
}</syntaxhighlight>
as an explicit argument. This is supposed to happen automatically.
 
Further modified version that supports compact representation of longer non-repeating substrings, just like the [[#C|C solution]] (so should be fully compatible with that solution for both encoding and decoding):
Note also that Perl 6 regexes don't care about unquoted whitespace, and that backrefs
count from 0, not from 1.
 
<syntaxhighlight lang="perl">sub encode {
<lang perl6>sub encode($str) { $str.subst(/(.) $0*/, -> $/ { $/.chars ~ $0 ~ ' ' }, :g); }
my $str = shift;
my $ret = "";
my $nonrep = "";
while ($str =~ m/(.)\1{0,127}|\z/gs) {
my $len = length($&);
if (length($nonrep) && (length($nonrep) == 127 || $len != 1)) {
$ret .= pack("C", 128 + length($nonrep)) . $nonrep;
$nonrep = "";
}
if ($len == 1) { $nonrep .= $1 }
elsif ($len > 1) { $ret .= pack("C", $len) . $1 }
}
return $ret;
}
 
sub decode {
sub decode($str) { $str.subst(/(\d+) (.) ' '/, -> $/ {$1 x $0}, :g); }
my $str = shift;
my $ret = "";
for (my $i = 0; $i < length($str);) {
my $len = unpack("C", substr($str, $i, 1));
if ($len <= 128) {
$ret .= substr($str, $i + 1, 1) x $len;
$i += 2;
}
else {
$ret .= substr($str, $i + 1, $len - 128);
$i += 1 + $len - 128;
}
}
return $ret;
}</syntaxhighlight>
 
Demonstration of the third version:
my $e = encode('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW');
say $e;
say decode($e);</lang>
 
<syntaxhighlight lang="perl">use Data::Dump qw(dd);
Output:
dd my $str = "XXXXXABCDEFGHIoooooooooooooooooooooooooAAAAAA";
dd my $enc = encode($str);
dd decode($enc);</syntaxhighlight>
 
{{out}}
<pre>12W 1B 12W 3B 24W 1B 14W
<pre>
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
"XXXXXABCDEFGHIoooooooooooooooooooooooooAAAAAA"
"\5X\x89ABCDEFGHI\31o\6A"
"XXXXXABCDEFGHIoooooooooooooooooooooooooAAAAAA"
</pre>
 
=={{header|Phix}}==
Based on [[Run-length_encoding#Euphoria|Euphoria]], but uses a few string in place of sequence.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">encode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">ch</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">count</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">}</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</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: #000000;">r</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">count</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">decode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">r</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;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">s</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;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">encode</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">s</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">decode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
Note the character hints are desktop/Phix only and don't appear under p2js.
<pre>
{12,87'W',1,66'B',12,87'W',3,66'B',24,87'W',1,66'B',14,87'W'}
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
</pre>
 
=={{header|PHP}}==
<langsyntaxhighlight lang="php"><?php
function encode($str) {
{
return preg_replace('/(.)\1*/e', 'strlen($0) . $1', $str);
return preg_replace_callback('/(.)\1*/', function ($match) {
return strlen($match[0]) . $match[1];
}, $str);
}
 
function decode($str) {
{
return preg_replace('/(\d+)(\D)/e', 'str_repeat($2, $1)', $str);
return preg_replace_callback('/(\d+)(\D)/', function($match) {
return str_repeat($match[2], $match[1]);
}, $str);
}
 
echo encode('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'), "\n"PHP_EOL;
echo decode('12W1B12W3B24W1B14W'), "\n"PHP_EOL;
?></langsyntaxhighlight>
 
=={{header|Picat}}==
===While loop===
Quite slow.
<syntaxhighlight lang="picat">rle(S) = RLE =>
RLE = "",
Char = S[1],
I = 2,
Count = 1,
while (I <= S.len)
if Char == S[I] then
Count := Count + 1
else
RLE := RLE ++ Count.to_string() ++ Char.to_string(),
Count := 1,
Char := S[I]
end,
I := I + 1
end,
RLE := RLE ++ Count.to_string() ++ Char.to_string().</syntaxhighlight>
 
===Using positions of different chars===
Much faster than <code>rle/1</code>.
<syntaxhighlight lang="picat">rle2(S) = RLE =>
Ix = [1] ++ [I : I in 2..S.len, S[I] != S[I-1]] ++ [S.len+1],
Diffs = diff(Ix),
RLE = [Diffs[I].to_string() ++ S[Ix[I]].to_string() : I in 1..Diffs.len].join('').</syntaxhighlight>
===Recursive approach===
The fastest version.
<syntaxhighlight lang="picat">rle3(S) = RLE =>
rle3(S.tail(),S[1],1,[],RLE).
 
rle3([],LastChar,Count,RLE1,RLE) =>
RLE = (RLE1 ++ [Count.to_string(),LastChar.to_string()]).join('').
 
rle3([C|T],LastChar,Count,RLE1,RLE) =>
C == LastChar ->
rle3(T,C,Count+1,RLE1,RLE)
;
rle3(T,C,1,RLE1++[Count.to_string()++LastChar.to_string()],RLE).</syntaxhighlight>
 
===Test===
Encode and decode (only using <code>rle3/1</code>):
<syntaxhighlight lang="picat">go =>
S = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWWA",
println(S),
RLE = rle3(S),
println(rle=RLE),
D = rl_decode(RLE),
println(D),
if D == S then
println(ok)
else
println(not_ok)
end,
nl.</syntaxhighlight>
 
{{out}}
<pre>WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWWA
rle = 12W1B12W3B24W1B14W1A
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWWA
ok</pre>
 
===Benchmark on larger string===
A benchmark on a larger string (30_000) clearly shows that rle3/1 is the fastest.
<syntaxhighlight lang="picat">go2 =>
_ = random2(),
Alpha = "AB",
Len2 = Alpha.len,
_ = random2(),
S = [Alpha[random(1,Len2)] : _ in 1..30_000],
if S.len < 200 then println(s=S) end ,
println("rle/1:"),
time(_=rle(S)),
println("rle2/1:"),
time(_=rle2(S)),
println("rle3/1:"),
time(_=rle3(S)),
nl.</syntaxhighlight>
 
{{out}}
<pre>rle/1:
 
CPU time 4.02 seconds.
 
rle3/1:
 
CPU time 2.422 seconds.
 
rle3/1:
 
CPU time 0.812 seconds.</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de encode (Str)
(pack
(make
Line 2,127 ⟶ 4,618:
(prinl "Data: " "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
(prinl "Encoded: " (encode @))
(prinl "Decoded: " (decode @)) )</langsyntaxhighlight>
Output:
<pre>Data: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 2,134 ⟶ 4,625:
 
=={{header|PL/I}}==
<syntaxhighlight lang="pli">declare (c1, c2) character (1);
<lang PL/I>
declare (c1, c2) character (1);
declare run_length fixed binary;
declare input file;
Line 2,172 ⟶ 4,662:
end;
put edit ((c do i = 1 to run_length)) (a);
end;</syntaxhighlight>
end;
</lang>
 
=={{header|PowerBASIC}}==
Line 2,179 ⟶ 4,668:
This version can handle any arbitrary string that doesn't contain numbers (not just letters). (A flag value could be added which would allow the inclusion of ''any'' character, but such a flag isn't in this example.)
 
<langsyntaxhighlight lang="powerbasic">FUNCTION RLDecode (i AS STRING) AS STRING
DIM Loop0 AS LONG, rCount AS STRING, outP AS STRING, m AS STRING
 
Line 2,230 ⟶ 4,719:
'in PB/Win, "?" = MSGBOX; in PB/DOS & PB/CC. "?" = PRINT
? initial & $CRLF & encoded & $CRLF & decoded
END FUNCTION</langsyntaxhighlight>
 
Outputs are similar to those in [[#BASIC|BASIC]], above.
 
=={{header|PowerShell}}==
<langsyntaxhighlight lang="powershell">function Compress-RLE ($s) {
$re = [regex] '(.)\1*'
$ret = ""
Line 2,252 ⟶ 4,741:
}
return $ret
}</langsyntaxhighlight>
Output:
<pre>PS> Compress-RLE "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
Line 2,258 ⟶ 4,747:
PS> Expand-RLE "12W1B12W3B24W1B14W"
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|Prolog}}==
Works with SWI-Prolog.<br>
This code is inspired from a code found here : http://groups.google.com/group/comp.lang.prolog/browse_thread/thread/b053ea2512e8b350 (author : Pascal J. Bourguignon).
<langsyntaxhighlight Prologlang="prolog">% the test
run_length :-
L = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW",
Line 2,368 ⟶ 4,858:
 
run(Var,[Other|RRest], [1,Var],[Other|RRest]):-
dif(Var,Other).</langsyntaxhighlight>
Output :
<pre> ?- run_length.
Line 2,380 ⟶ 4,870:
 
=={{header|Pure}}==
<langsyntaxhighlight lang="pure">using system;
 
encode s = strcat $ map (sprintf "%d%s") $ encode $ chars s with
Line 2,394 ⟶ 4,884:
let s = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
let r = encode s; // "12W1B12W3B24W1B14W"
decode r;</langsyntaxhighlight>
 
=={{header|PureBasic}}==
{{trans|PowerBasic}} with some optimations to use pointers instead of string functions. According to the task description it works with uppercase A - Z. In this implementation it also functions with all characters that are non-digits and whose value is non-zero.
<langsyntaxhighlight PureBasiclang="purebasic">Procedure.s RLDecode(toDecode.s)
Protected.s repCount, output, currChar, tmp
Protected *c.Character = @toDecode
Line 2,463 ⟶ 4,953:
Input()
CloseConsole()
EndIf</langsyntaxhighlight>
Sample output:
<pre>Type something: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWW
Line 2,472 ⟶ 4,962:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">def encode(input_string):
count = 1
prev = ''None
lst = []
for character in input_string:
if character != prev:
if prev:
entry = (prev, count)
lst.append(entry)
#print lst
count = 1
prev = character
Line 2,487 ⟶ 4,976:
count += 1
else:
entry = (character,count)try:
lst.append( entry = (character, count)
return lst.append(entry)
return (lst, 0)
 
except Exception as e:
 
print("Exception encountered {e}".format(e=e))
return (e, 1)
def decode(lst):
q = ""[]
for character, count in lst:
q += .append(character * count)
return ''.join(q)
 
#Method call
value = encode("aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa")
if value[1] == 0:
decode([('a', 5), ('h', 6), ('m', 7), ('u', 1), ('i', 7), ('a', 6)])</lang>
print("Encoded value is {}".format(value[0]))
decode(value[0])</syntaxhighlight>
 
Functional
{{works with|Python|2.4}}
<langsyntaxhighlight lang="python">from itertools import groupby
def encode(input_string):
return [(len(list(g)), k) for k,g in groupby(input_string)]
Line 2,512 ⟶ 5,006:
 
encode("aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa")
decode([(5, 'a'), (6, 'h'), (7, 'm'), (1, 'u'), (7, 'i'), (6, 'a')])</langsyntaxhighlight>
 
<br>'''By regular expression'''<br>
The simplified input range of only uppercase characters allows a simple regular expression to be applied repeatedly for encoding, and another for decoding:
<langsyntaxhighlight lang="python">from re import sub
 
def encode(text):
Line 2,537 ⟶ 5,031:
 
textin = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
assert decode(encode(textin)) == textin</langsyntaxhighlight>
 
=={{header|Quackery}}==
 
<code>lookandsay</code> is defined at [[Look-and-say sequence#Quackery]].
 
<syntaxhighlight lang="quackery"> [ lookandsay ] is encode ( $ --> $ )
 
[ $ "" 0 rot
witheach
[ dup
char 0 char 9 1+
within iff
[ char 0 -
swap 10 * + ]
else
[ swap of join
0 ] ]
drop ] is decode ( $ --> $ )
 
$ "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
dup echo$ cr
encode
dup echo$ cr
decode
echo$ cr</syntaxhighlight>
 
{{out}}
 
<pre>WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|R}}==
R has a built-in function, rle, for run length encoding. This modification allows input and output in the forms specified above.
<langsyntaxhighlight Rlang="rsplus">runlengthencoding <- function(x)
{
splitx <- unlist(strsplit(input, ""))
Line 2,549 ⟶ 5,075:
 
input <- "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
runlengthencoding(input)</langsyntaxhighlight>
Similarly, inverse.rle provides decompression after a run length encoding.
<langsyntaxhighlight Rlang="rsplus">inverserunlengthencoding <- function(x)
{
lengths <- as.numeric(unlist(strsplit(output, "[[:alpha:]]")))
Line 2,561 ⟶ 5,087:
 
output <- "12W1B12W3B24W1B14W"
inverserunlengthencoding(output)</langsyntaxhighlight>
 
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
(define (encode str)
Line 2,571 ⟶ 5,097:
(define (decode str)
(regexp-replace* #px"([0-9]+)(.)" str (λ (m n c) (make-string (string->number n) (string-ref c 0)))))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
Note that Raku regexes don't care about unquoted whitespace, and that backrefs
count from 0, not from 1.
 
<syntaxhighlight lang="raku" line>sub encode($str) { $str.subst(/(.) $0*/, { $/.chars ~ $0 }, :g) }
 
sub decode($str) { $str.subst(/(\d+) (.)/, { $1 x $0 }, :g) }
 
my $e = encode('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW');
say $e;
say decode($e);</syntaxhighlight>
 
Output:
 
<pre>12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|REXX}}==
===version 1===
The task (input) rule was relaxed a bit as this program accepts upper- and lowercase input.
The task (input) rule was relaxed a bit as this program accepts upper─ and lowercase input.
===encoding===
<lang rexx>/*REXX program encodes string by using a run-length scheme (min len=2).*/
parse arg x /*normally, input would be a file*/
def='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
if x=='' then x=def /*No input? Then use the default*/
Lx=length(x) /*get the length of the X string.*/
y= /*Y is the output string (so far)*/
do j=1 to Lx /*warning! J is modified below.*/
c=substr(x,j,1) /*pick a character, check for err*/
if \datatype(c,'m') then do;say "error!: data isn't alphabetic";exit 13; end
r=0 /*R is NOT the number of chars. */
 
An error message is generated if the input text is invalid.
do k=j+1 to Lx while substr(x,k,1)==c
r=r+1 /*R is a replication count. */
end /*k*/
 
In addition, a &nbsp;''yay''&nbsp; or &nbsp;''nay''&nbsp; message is also displayed if the decoding of the encoding was successful.
if r==0 then Y = Y || c /*C wan't repeated, just OUT it.*/
else Y = Y || r || c /*add it to the encoded string. */
j=j+r /*A bad thing to do, but simple. */
end /*j*/
 
Note that this REXX version (for encoding and decoding) uses a &nbsp; ''replication'' &nbsp; count, not the &nbsp; ''count'' &nbsp; of characters,
say ' input=' x
<br>so a replication count of &nbsp; '''11''' &nbsp; represents a count of &nbsp; '''12''' &nbsp; characters.
say 'encoded=' y
<syntaxhighlight lang="rexx">/*REXX program encodes and displays a string by using a run─length encoding scheme. */
/*stick a fork in it, we're done.*/</lang>
parse arg input . /*normally, input would be in a file. */
'''output''' when using default input:'
default= 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
<pre style="overflow:scroll">
if input=='' | input=="," then input= default /*Not specified? Then use the default.*/
input= WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
encode= RLE(input) ; say ' input=' input /*encode input string; display input. */
output= 11WB11W2B23WB13W
say 'encoded=' encode /* display run─len*/
decode= RLD(encode); say 'decoded=' decode /*decode the run─len; display decode.*/
if decode==input then say 'OK'; else say "¬ OK" /*display yay or nay (success/failure).*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
err: say; say "***error*** input data isn't alphabetic:" c; say; exit 13
/*──────────────────────────────────────────────────────────────────────────────────────*/
RLE: procedure; parse arg x; $= /*$: is the output string (so far). */
Lx= length(x) /*get length of the plain text string. */
do j=1 by 0 to Lx; c= substr(x, j, 1) /*obtain a character from plain text. */
if \datatype(c, 'M') then call err /*Character not a letter? Issue error.*/
r= 0 /*R: is NOT the number of characters. */
do k=j+1 to Lx while substr(x, k, 1)==c /*while characters ≡ C */
r= r + 1 /*bump the replication count for a char*/
end /*k*/
j= j + r + 1 /*increment (add to) the DO loop index.*/
if r==0 then $= $ || c /*don't use R if it is equal to zero.*/
else $= $ || r || c /*add character to the encoded string. */
end /*j*/; return $ /*return the encoded string to caller. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
RLD: procedure; parse arg x; $= /*$: is the output string (so far). */
Lx= length(x) /*get the length of the encoded string.*/
do j=1 by 0 to Lx; c= substr(x, j, 1) /*obtain a character from run encoding.*/
if \datatype(c, 'W') then do; $= $ || c; j= j + 1; iterate /*j*/
end /* [↑] a loner char, add it to output.*/
#= 1 /* [↓] W: use a Whole number*/
do k=j+1 to Lx while datatype(substr(x,k,1), 'w') /*while numeric*/
#= # + 1 /*bump the count of the numeric chars. */
end /*k*/
n= substr(x, j, #) + 1 /*#: the length of encoded character. */
$= $ || copies( substr(x, k, 1), n) /*N: is now the number of characters. */
j= j + # + 1 /*increment the DO loop index by D+1. */
end /*j*/; return $ /*return the decoded string to caller. */</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
input= WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
encoded= 11WB11W2B23WB13W
decoded= WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
===decodingversion 2===
<syntaxhighlight lang="rexx">
<lang rexx>/*REXX program decodes string by using a run-length scheme (min len=2).*/
/*REXX*/
parse arg x /*normally, input would be a file*/
s='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
if x=='' then x='11WB11W2B23WB13W' /*No input? Then use the default*/
Say ' s='s
Lx=length(x) /*get the length of the X string.*/
enc=encode(s)
y= /*Y is the output string (so far)*/
Say 'enc='enc
do j=1 to Lx /*warning! J is modified below.*/
dec=decode(enc)
c=substr(x,j,1)
Say 'dec='dec
if \datatype(c,'W') then do /*a loner char, simply add to OUT*/
if dec==s Then Say 'OK'
y=y || c
Exit
iterate
end
d=1
do k=j+1 to Lx while datatype(substr(x,k,1),'w') /*look for #end*/
d=d+1 /*d is the number of digs so far.*/
end /*k*/
 
encode: Procedure
n=substr(x,j,d)+1 /*D is length of encoded number.*/
Parse Arg s
y=y || copies(substr(x,k,1),n) /*N is now the number of chars. */
c=left(s,1)
j=j+d /*A bad thing to do, but simple. */
cnt=1
end /*j*/
ol=''
Do i=2 To length(s)
If substr(s,i,1)=c Then
cnt=cnt+1
Else Do
Call o cnt||c
c=substr(s,i,1)
cnt=1
End
End
Call o cnt||c
Return ol
 
decode: Procedure
say ' input=' x
Parse Arg s
say 'decoded=' y
abc='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
/*stick a fork in it, we're done.*/</lang>
ol=''
'''output''' when using the default input:
Do While s<>''
<pre style="overflow:scroll">
p=verify(s,abc,'M')
input= 11WB11W2B23WB13W
Parse Var s cnt =(p) c +1 s
decoded= WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Call o copies(c,cnt)
End
Return ol
 
o: ol=ol||arg(1)
Return</syntaxhighlight>
{{out}}
<pre> s=WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
enc=12W1B12W3B24W1B14W
dec=WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
OK</pre>
 
===version 3===
No need to output counts that are 1
<syntaxhighlight lang="rexx">
/*REXX*/
s='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
Say ' s='s
enc=encode(s)
Say 'enc='enc
dec=decode(enc)
Say 'dec='dec
if dec==s Then Say 'OK'
Exit
 
encode: Procedure
Parse Arg s
c=left(s,1)
cnt=1
ol=''
Do i=2 To length(s)
If substr(s,i,1)=c Then
cnt=cnt+1
Else Do
If cnt=1 Then
Call o c
Else
Call o cnt||c
c=substr(s,i,1)
cnt=1
End
End
Call o cnt||c
Return ol
 
decode: Procedure
Parse Arg s
abc='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
ol=''
Do While s<>''
p=verify(s,abc,'M')
If pos(left(s,1),abc)>0 Then Do
Parse Var s c +1 s
Call o c
End
Else Do
Parse Var s cnt =(p) c +1 s
Call o copies(c,cnt)
End
End
Return ol
 
o: ol=ol||arg(1)
Return</syntaxhighlight>
{{out}}
<pre> s=WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
enc=12WB12W3B24WB14W
dec=WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
OK</pre>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
# Project : Run-length encoding
 
load "stdlib.ring"
test = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
num = 0
nr = 0
decode = newlist(7,2)
for n = 1 to len(test) - 1
if test[n] = test[n+1]
num = num + 1
else
nr = nr + 1
decode[nr][1] = (num + 1)
decode[nr][2] = test[n]
see "" + (num + 1) + test[n]
num = 0
ok
next
see "" + (num + 1) + test[n]
see nl
nr = nr + 1
decode[nr][1] = (num + 1)
decode[nr][2] = test[n]
for n = 1 to len(decode)
dec = copy(decode[n][2], decode[n][1])
see dec
next
</syntaxhighlight>
Output:
<pre>
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|RPL}}==
≪ DUP 1 DUP SUB → in c
≪ "" 1
2 in SIZE '''FOR''' j
in j DUP SUB
'''IF''' DUP c == '''THEN''' DROP 1 +
'''ELSE'''
ROT ROT
→STR + c +
SWAP 'c' STO 1
'''END'''
'''NEXT'''
→STR + c +
≫ ≫ ‘<span style="color:blue">RLENC</span>’ STO
≪ → in
≪ "" 0
1 in SIZE '''FOR''' j
in j DUP SUB
'''IF''' DUP "A" ≥ '''THEN'''
ROT 1 4 ROLL '''START''' OVER + '''NEXT'''
SWAP DROP 0
'''ELSE''' STR→ SWAP 10 * + '''END'''
'''NEXT''' DROP
≫ ≫ ‘<span style="color:blue">RLDEC</span>’ STO
 
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" <span style="color:blue">RLENC</span> DUP <span style="color:blue">RLDEC</span>
{{out}}
<pre>
2: "12W1B12W3B24W1B14W"
1: "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
</pre>
 
=={{header|Ruby}}==
 
<lang ruby>def encode(string)
<br>'''Built-in'''<br>
 
Ruby has built-in run-length encoding in the form of <code>chunk</code>, here I provide a thin wrapper around it:
 
<syntaxhighlight lang="ruby">
# run_encode("aaabbbbc") #=> [["a", 3], ["b", 4], ["c", 1]]
def run_encode(string)
string
.chars
.chunk{|i| i}
.map {|kind, array| [kind, array.length]}
end
 
# run_decode([["a", 3], ["b", 4], ["c", 1]]) #=> "aaabbbbc"
def run_decode(char_counts)
char_counts
.map{|char, count| char * count}
.join
end
 
</syntaxhighlight>
 
<syntaxhighlight lang="ruby">def encode(string)
string.scan(/(.)(\1*)/).collect do |char, repeat|
[1 + repeat.length, char]
Line 2,645 ⟶ 5,379:
def decode(string)
string.scan(/(\d+)(\D)/).collect {|length, char| char * length.to_i}.join
end</langsyntaxhighlight>
 
This usage also seems to be idiomatic, and perhaps less cryptic:
<langsyntaxhighlight lang="ruby">def encode(string)
string.scan(/(.)(\1*)/).inject("") do |encoding, (char, repeat)|
encoding << (1 + repeat.length).to_s << char
Line 2,658 ⟶ 5,392:
decoding << char * length.to_i
end
end</langsyntaxhighlight>
 
<br>'''By regular expression'''<br>
The simplified input range of only uppercase characters allows a simple regular expression to be applied repeatedly for encoding, and another for decoding:
<langsyntaxhighlight lang="ruby">def encode(str)
str.gsub(/(.)\1*/) {$&.length.to_s + $1}
end
Line 2,668 ⟶ 5,402:
def decode(str)
str.gsub(/(\d+)(\D)/) {$2 * $1.to_i}
end</langsyntaxhighlight>
 
'''Test:'''
<langsyntaxhighlight lang="ruby">orig = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
p enc = encode(orig)
p dec = decode(enc)
puts "success!" if dec == orig</langsyntaxhighlight>
 
{{out}}
Line 2,684 ⟶ 5,418:
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">string$ = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
beg = 1
i = 1
Line 2,709 ⟶ 5,443:
beg = i
if i < len(press$) then goto [expand]
print " Expanded:";expand$</langsyntaxhighlight>Output:
<pre>Compressed:12W1B12W3B24W1B14W
Expanded:WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">fn encode(s: &str) -> String {
s.chars()
// wrap all values in Option::Some
.map(Some)
// add an Option::None onto the iterator to clean the pipeline at the end
.chain(std::iter::once(None))
.scan((0usize, '\0'), |(n, c), elem| match elem {
Some(elem) if *n == 0 || *c == elem => {
// the run continues or starts here
*n += 1;
*c = elem;
// this will not have an effect on the final string because it is empty
Some(String::new())
}
Some(elem) => {
// the run ends here
let run = format!("{}{}", n, c);
*n = 1;
*c = elem;
Some(run)
}
None => {
// the string ends here
Some(format!("{}{}", n, c))
}
})
// concatenate together all subresults
.collect()
}
 
fn decode(s: &str) -> String {
s.chars()
.fold((0usize, String::new()), |(n, text), c| {
if c.is_ascii_digit() {
// some simple number parsing
(
n * 10 + c.to_digit(10).expect("invalid encoding") as usize,
text,
)
} else {
// this must be the character that is repeated
(0, text + &format!("{}", c.to_string().repeat(n)))
}
})
.1
}
 
fn main() {
let text = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
let encoded = encode(text);
let decoded = decode(&encoded);
 
println!("original: {}\n encoded: {}\n decoded: {}", text, encoded, decoded);
assert_eq!(text, decoded);
}
</syntaxhighlight>
{{out}}
<pre>original: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
encoded: 12W1B12W3B24W1B14W
decoded: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|Scala}}==
Care is taken to use StringBuilder for performance reasons.
 
<langsyntaxhighlight lang="scala">def encode(s: String) = (1 until s.size).foldLeft((1, s(0), new StringBuilder)) {
case ((len, c, sb), index) if c != s(index) => sb.append(len); sb.append(c); (1, s(index), sb)
case ((len, c, sb), _) => (len + 1, c, sb)
Line 2,728 ⟶ 5,525:
for (Code(len, c) <- Code findAllIn s) sb.append(c * len.toInt)
sb.toString
}</langsyntaxhighlight>
 
A simpler (?) encoder:
<langsyntaxhighlight lang="scala">def encode(s:String) = {
s.foldLeft((0,s(0),""))( (t,c) => t match {case (i,p,s) => if (p==c) (i+1,p,s) else (1,c,s+i+p)})
match {case (i,p,s) => s+i+p}
}</langsyntaxhighlight>
 
To make it faster (it's also faster than the longer implementation above) just replace '''""''' with '''new StringBuilder''' and '''s+i+p''' with '''{s.append(i);s.append(p)}'''
 
A simpler (?) decoder (that can handle a string like "2AB", producing "AAB"):
<syntaxhighlight lang="scala">def decode(s: String, Code: scala.util.matching.Regex = """(\d+)?([a-zA-Z])""".r) =
Code.findAllIn(s).foldLeft("") { case (acc, Code(len, c)) =>
acc + c * Option(len).map(_.toInt).getOrElse(1)
}</syntaxhighlight>
 
=={{header|Scheme}}==
<langsyntaxhighlight lang="scheme">(define (run-length-decode v)
(apply string-append (map (lambda (p) (make-string (car p) (cdr p))) v)))
 
Line 2,753 ⟶ 5,556:
; ((12 . #\W) (1 . #\B) (12 . #\W) (3 . #\B) (24 . #\W) (1 . #\B) (14 . #\W))
(run-length-decode '((12 . #\W) (1 . #\B) (12 . #\W) (3 . #\B) (24 . #\W) (1 . #\B) (14 . #\W)))
; "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"</langsyntaxhighlight>
 
=={{header|sed}}==
The encode script:
<langsyntaxhighlight lang="sed">
/^$/ b
:start
Line 2,784 ⟶ 5,587:
s/^([0-9]+.)(.*)/\2\1/
b start
</syntaxhighlight>
</lang>
 
The decode script:
<langsyntaxhighlight lang="sed">
/^$/ b
:start
Line 2,809 ⟶ 5,612:
s/^0+//
b loop }
</syntaxhighlight>
</lang>
 
Example (assuming the scripts reside in the files <code>encode.sed</code> and <code>decode.sed</code>):
<langsyntaxhighlight lang="bash">
sed -rf encode.sed <<< "foo oops"
# 1f2o1 2o1p1s
Line 2,821 ⟶ 5,624:
(sed -rf decode.sed | sed -rf encode.sed) <<< 1000.
# 1000.
</syntaxhighlight>
</lang>
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "scanstri.s7i";
 
Line 2,859 ⟶ 5,662:
writeln(letterRleEncode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"));
writeln(letterRleDecode("12W1B12W3B24W1B14W"));
end func;</langsyntaxhighlight>
 
=={{header|SETL}}==
<syntaxhighlight lang="setl">program rle;
test := "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
 
print("Input:");
print(test);
print("Encoded:");
print(enc := rlencode(test));
print("Decoded:");
print(rldecode(enc));
 
proc rlencode(s);
loop while s /= "" do
part := span(s, s(1));
r +:= str #part + part(1);
end loop;
return r;
end proc;
 
proc rldecode(s);
loop while s /= "" do
num := span(s, "0123456789");
item := notany(s, "");
r +:= val num * item;
end loop;
return r;
end proc;
end program;</syntaxhighlight>
{{out}}
<pre>Input:
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Encoded:
12W1B12W3B24W1B14W
Decoded:
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|Sidef}}==
First solution:
<syntaxhighlight lang="ruby">func encode(str) {
str.gsub(/((.)(\2*))/, {|a,b| "#{a.len}#{b}" });
}
 
func decode(str) {
str.gsub(/(\d+)(.)/, {|a,b| b * a.to_i });
}</syntaxhighlight>
{{out}}
<pre>12W1B12W3B24W1B14W</pre>
 
Second solution, encoding the length into a byte:
<syntaxhighlight lang="ruby">func encode(str) {
str.gsub(/(.)(\1{0,254})/, {|a,b| b.len+1 -> chr + a});
}
 
func decode(str) {
var chars = str.chars;
var r = '';
(chars.len/2 -> int).range.each { |i|
r += (chars[2*i + 1] * chars[2*i].ord);
}
return r;
}</syntaxhighlight>
{{out}}
<pre>"\fW\1B\fW\3B\30W\1B\16W"</pre>
 
=={{header|Smalltalk}}==
See [[Run-length encoding/Smalltalk]]
A "functional" version without RunArray:
{{works with|Smalltalk/X}} (and others)
 
<syntaxhighlight lang="smalltalk">|compress decompress|
compress := [:string |
String streamContents:[:out |
|count prev|
count := 0.
(string,'*') "trick to avoid final run handling in loop"
inject:nil
into:[:prevChar :ch |
ch ~= prevChar ifTrue:[
count = 0 ifFalse:[
count printOn:out.
out nextPut:prevChar.
count := 0.
].
].
count := count + 1.
ch
]
]
].
 
decompress := [:string |
String streamContents:[:out |
string readingStreamDo:[:in |
[in atEnd] whileFalse:[
|n ch|
n := Integer readFrom:in.
ch := in next.
out next:n put:ch.
]
]
].
].</syntaxhighlight>
 
<syntaxhighlight lang="smalltalk">compress value:'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
-> '12W1B12W3B24W1B14W'
 
decompress value:'12W1B12W3B24W1B14W'
-> 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'</syntaxhighlight>
 
Most Smalltalk dialects include a class named "RunArray", which can be used as:
{{works with|Smalltalk/X}}
{{works with|VisualWorks}}
<syntaxhighlight lang="smalltalk">compress := [:string |
String streamContents:[:out |
string asRunArray runsDo:[:count :char |
count printOn:out. out nextPut:char]]].</syntaxhighlight>
 
=={{header|SNOBOL4}}==
Line 2,870 ⟶ 5,789:
{{works with|CSnobol}}
 
<langsyntaxhighlight SNOBOL4lang="snobol4">* # Encode RLE
define('rle(str)c,n') :(rle_end)
rle str len(1) . c :f(return)
Line 2,888 ⟶ 5,807:
str = rle(str); output = str
str = elr(str); output = str
end</langsyntaxhighlight>
 
Output:
Line 2,894 ⟶ 5,813:
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|SparForte}}==
As a structured script.
<syntaxhighlight lang="ada">#!/usr/local/bin/spar
pragma is
annotate( summary, "rle" );
annotate( description, "Given a string containing uppercase characters (A-Z)," );
annotate( description, "compress repeated 'runs' of the same character by" );
annotate( description, "storing the length of that run, and provide a function to" );
annotate( description, "reverse the compression. The output can be anything, as" );
annotate( description, "long as you can recreate the input with it." );
annotate( description, "" );
annotate( description, "Example:" );
annotate( description, "Input: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" );
annotate( description, "Output: 12W1B12W3B24W1B14W" );
annotate( see_also, "http://rosettacode.org/wiki/Run-length_encoding" );
annotate( author, "Ken O. Burtch" );
license( unrestricted );
restriction( no_external_commands );
end pragma;
 
procedure rle is
 
function to_rle( s : string ) return string is
begin
if strings.length( s ) = 0 then
return "";
end if;
declare
result : string;
code : character;
prefix : string;
first : natural := 1;
index : natural := 1;
begin
while index <= strings.length( s ) loop
first := index;
index := @+1;
code := strings.element( s, positive(first) );
while index <= strings.length( s ) loop
exit when code /= strings.element( s, positive(index) );
index := @+1;
exit when index-first = 99;
end loop;
prefix := strings.trim( strings.image( index - first ), trim_end.left );
result := @ & prefix & code;
end loop;
return result;
end;
end to_rle;
 
function from_rle( s : string ) return string is
begin
if strings.length( s ) = 0 then
return "";
end if;
declare
result : string;
index : positive := 1;
prefix : string;
code : character;
begin
loop
prefix := "" & strings.element( s, index );
index := @+1;
if strings.is_digit( strings.element( s, index ) ) then
prefix := @ & strings.element( s, index );
index := @+1;
end if;
code := strings.element( s, index );
index := @+1;
result := @ & ( numerics.value( prefix ) * code );
exit when natural(index) > strings.length( s );
end loop;
return result;
end;
end from_rle;
 
begin
? to_rle( "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" );
? from_rle( "12W1B12W3B24W1B14W");
end rle;</syntaxhighlight>
 
=={{header|SQL}}==
Line 2,899 ⟶ 5,900:
<br>
* RLE encoding
<syntaxhighlight lang="sql">
<lang SQL>
-- variable table
drop table if exists var;
Line 2,947 ⟶ 5,948:
where noWithinGroup = 1
) Rle_Compressed
</syntaxhighlight>
</lang>
 
* RLE decoding
<syntaxhighlight lang="sql">
<lang SQL>
-- variable table
DROP TABLE IF EXISTS var;
Line 3,013 ⟶ 6,014:
string_agg(replicated_Letter, '' ORDER BY group_no) decoded_string
FROM lettersReplicated
</syntaxhighlight>
</lang>
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang="sml">fun encode str =
let
fun aux (sub, acc) =
Line 3,032 ⟶ 6,033:
 
fun decode lst =
concat (map (fn (c,n) => implode (List.tabulate (n, fn _ => c))) lst)</langsyntaxhighlight>
Example:
<pre>
Line 3,040 ⟶ 6,041:
- decode [(#"a",5),(#"h",6),(#"m",7),(#"u",1),(#"i",7),(#"a",6)];
val it = "aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa" : string
</pre>
 
=={{header|Swift}}==
Using array as the internal representation of the encoded input:
<syntaxhighlight lang="swift">import Foundation
 
// "WWWBWW" -> [(3, W), (1, B), (2, W)]
func encode(input: String) -> [(Int, Character)] {
return input.characters.reduce([(Int, Character)]()) {
if $0.last?.1 == $1 { var r = $0; r[r.count - 1].0++; return r }
return $0 + [(1, $1)]
}
}
 
// [(3, W), (1, B), (2, W)] -> "WWWBWW"
func decode(encoded: [(Int, Character)]) -> String {
return encoded.reduce("") { $0 + String(count: $1.0, repeatedValue: $1.1) }
}
</syntaxhighlight>
 
'''Usage:'''
 
<syntaxhighlight lang="swift">
let input = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
let output = decode(encode(input))
print(output == input)
</syntaxhighlight>
 
{{Out}}
 
<pre>true</pre>
 
Converting encoded array into the string and then decoding it using NSScanner:
 
<syntaxhighlight lang="swift">// "3W1B2W" -> "WWWBWW"
func decode(encoded: String) -> String {
let scanner = NSScanner(string: encoded)
var char: NSString? = nil
var count: Int = 0
var out = ""
 
while scanner.scanInteger(&count) {
while scanner.scanCharactersFromSet(NSCharacterSet.letterCharacterSet(), intoString: &char) {
out += String(count: count, repeatedValue: Character(char as! String))
}
}
 
return out
}
</syntaxhighlight>
 
<syntaxhighlight lang="swift">let encodedString = encode(input).reduce("") { $0 + "\($1.0)\($1.1)" }
print(encodedString)
let outputString = decode(encodedString)
print(outputString == input)
</syntaxhighlight>
 
{{Out}}
<pre>
12W1B12W3B24W1B14W
true
</pre>
 
=={{header|Tcl}}==
The encoding is an even-length list with elements <tt>{count char ...}</tt>
<langsyntaxhighlight lang="tcl">proc encode {string} {
set encoding {}
# use a regular expression to match runs of one character
Line 3,058 ⟶ 6,120:
}
return $decoded
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="tcl">set str "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
set enc [encode $str] ;# ==> {12 W 1 B 12 W 3 B 24 W 1 B 14 W}
set dec [decode $enc]
if {$str eq $dec} {
puts "success"
}</langsyntaxhighlight>
 
=={{header|TMG}}==
Unix TMG is designed to process and generate files rather than process text in memory. Therefore encoding and decoding parts can be done in separate programs.
 
Encoding:
<syntaxhighlight lang="unixtmg">loop: ordcop [lch?]\loop;
ordcop: ord/copy;
ord: char(ch)/last [ch!=lch?]\new [cnt++] fail;
new: ( [lch?] parse(out) | () ) [lch=ch] [cnt=1] fail;
out: decimal(cnt) scopy = { 2 1 };
last: parse(out) [lch=0];
copy: smark any(!<<>>);
ch: 0;
lch: 0;
cnt: 0;</syntaxhighlight>
 
Decoding:
<syntaxhighlight lang="unixtmg">loop: readint(n) copy\loop;
copy: smark any(!<<>>)
repeat: [n?] parse(( scopy )) [--n>0?]\repeat;
/* Reads decimal integer */
readint: proc(n;i) ignore(<<>>) [n=0] inta
int1: [n = n*12+i] inta\int1;
inta: char(i) [i<72?] [(i =- 60)>=0?];
i: 0;
n: 0;</syntaxhighlight>
 
=={{header|TSE SAL}}==
<syntaxhighlight lang="tsesal">
STRING PROC FNStringGetDecodeStringCharacterEqualCountS( STRING inS )
STRING s1[255] = ""
STRING s2[255] = ""
STRING s3[255] = ""
STRING s4[255] = ""
INTEGER I = 0
INTEGER J = 0
INTEGER K = 0
INTEGER L = 0
K = Length( inS )
I = 1 - 1
REPEAT
J = 1 - 1
s3 = ""
REPEAT
I = I + 1
J = J + 1
s1 = SubStr( inS, I, 1 )
s3 = s3 + s1
s4 = SubStr( inS, I + 1, 1 )
UNTIL ( NOT ( s4 IN '0'..'9' ) )
FOR L = 1 TO Val( s3 )
s2 = s2 + s4
ENDFOR
I = I + 1
UNTIL ( I >= ( K - 1 ) )
RETURN( s2 )
END
//
STRING PROC FNStringGetEncodeStringCharacterEqualCountS( STRING inS )
STRING s1[255] = ""
STRING s2[255] = ""
INTEGER I = 0
INTEGER J = 0
INTEGER K = 0
K = Length( inS )
I = 1 - 1
REPEAT
J = 1 - 1
REPEAT
I = I + 1
J = J + 1
s1 = SubStr( inS, I, 1 )
UNTIL ( NOT ( SubStr( inS, I + 1, 1 ) == s1 ) )
s2 = s2 + Str( J ) + s1
UNTIL ( I >= ( K - 1 ) )
RETURN( s2 )
END
//
STRING PROC FNStringGetEncodeDecodeStringCharacterEqualCountS( STRING inS )
STRING s1[255] = FNStringGetEncodeStringCharacterEqualCountS( inS )
STRING s2[255] = FNStringGetDecodeStringCharacterEqualCountS( s1 )
RETURN( s2 )
END
//
PROC Main()
STRING s1[255] = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
STRING s2[255] = ""
IF ( NOT ( Ask( "string: get: encode: decode: string: character: equal: count: inS = ", s1, _EDIT_HISTORY_ ) ) AND ( Length( s1 ) > 0 ) ) RETURN() ENDIF
s2 = FNStringGetEncodeDecodeStringCharacterEqualCountS( s1 )
Warn( "equal strings if result is 1", ",", " ", "and the result is", ":", " ", s1 == s2 )
END
</syntaxhighlight>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT,{}
input="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW",output=""
Line 3,078 ⟶ 6,235:
PRINT input
PRINT output
</syntaxhighlight>
</lang>
Output:
<pre>
Line 3,084 ⟶ 6,241:
12W1B12W3B24W1B14W
</pre>
 
=={{header|UNIX Shell}}==
{{works with|bash}}
<syntaxhighlight lang="bash">encode() {
local phrase=$1
[[ -z $phrase ]] && return
local result="" count=0 char=${phrase:0:1}
for ((i = 0; i < ${#phrase}; i++)); do
if [[ ${phrase:i:1} == "$char" ]]; then
((count++))
else
result+="$(encode_sequence "$count" "$char")"
char=${phrase:i:1}
count=1
fi
done
result+="$(encode_sequence "$count" "$char")"
echo "$result"
}
 
encode_sequence() {
local count=$1 char=$2
((count == 1)) && count=""
echo "${count}${char}"
}
 
decode() {
local phrase=$1
local result=""
local count char
 
while [[ $phrase =~ ([[:digit:]]+)([^[:digit:]]) ]]; do
printf -v phrase "%s%s%s" \
"${phrase%%${BASH_REMATCH[0]}*}" \
"$(repeat "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}")" \
"${phrase#*${BASH_REMATCH[0]}}"
done
echo "$phrase"
}
 
repeat() {
local count=$1 char=$2
local result
# string of count spaces
printf -v result "%*s" "$count" ""
# replace spaces with the char
echo "${result// /$char}"
}</syntaxhighlight>
Demo
<syntaxhighlight lang="bash">str="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
enc=$(encode "$str")
dec=$(decode "$enc")
declare -p str enc dec
[[ $str == "$dec" ]] && echo success || echo failure</syntaxhighlight>
Output
<pre>declare -- str="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
declare -- enc="12WB12W3B24WB14W"
declare -- dec="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
success</pre>
 
=={{header|Ursala}}==
Line 3,089 ⟶ 6,305:
which is a second order function taking a binary predicate that decides
when consecutive items of an input list belong to the same run.
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
 
Line 3,104 ⟶ 6,320:
<
encode test_data,
decode encode test_data></langsyntaxhighlight>
The output shows an encoding of the test data, and a decoding of the encoding, which
matches the original test data.
<pre>12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|VBA}}==
<syntaxhighlight lang="vb">
Option Explicit
 
Sub Main()
Dim p As String
p = length_encoding("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
Debug.Print p
Debug.Print length_decoding(p)
End Sub
 
Private Function length_encoding(S As String) As String
Dim F As String, r As String, a As String, n As Long, c As Long, k As Long
r = Left(S, 1)
c = 1
For n = 2 To Len(S)
If r <> Mid(S, n, 1) Then
a = a & c & r
r = Mid(S, n, 1)
c = 1
Else
c = c + 1
End If
Next
length_encoding = a & c & r
End Function
 
Private Function length_decoding(S As String) As String
Dim F As Long, r As String, a As String
For F = 1 To Len(S)
If IsNumeric(Mid(S, F, 1)) Then
r = r & Mid(S, F, 1)
Else
a = a & String(CLng(r), Mid(S, F, 1))
r = vbNullString
End If
Next
length_decoding = a
End Function</syntaxhighlight>
{{out}}
<pre>12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
Line 3,116 ⟶ 6,375:
Newlines are not converted (the regular expression does not count newlines).
This methods supports any type of input.
<langsyntaxhighlight lang="vedit">:RL_ENCODE:
BOF
While (!At_EOF) {
Line 3,146 ⟶ 6,405:
}
}
Return</langsyntaxhighlight>
 
=={{header|V (Vlang)}}==
<syntaxhighlight lang="Zig">
const test = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
 
fn main() {
encoded := encode(test)
println(encoded)
println(decode(encoded))
}
 
fn encode(data string) string {
mut encode :=""
mut temp := []u8{}
for key, value in data {
if key > 1 && value != data[key - 1] {
encode += temp.len.str() + temp[0].ascii_str()
temp.clear()
}
temp << value
}
encode += temp.len.str() + temp[0].ascii_str()
temp.clear()
return encode
}
 
fn decode(data string) string {
mut decode :=""
mut temp := []u8{}
for value in data {
if value.is_digit() == false {
decode += value.repeat(temp.bytestr().int())
temp.clear()
}
else {temp << value}
}
return decode
}
</syntaxhighlight>
 
{{out}}
<pre>
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-pattern}}
<syntaxhighlight lang="wren">import "./pattern" for Pattern
 
var p = Pattern.new("/u") // match any upper case letter
 
var encode = Fn.new { |s|
if (s == "") return s
var e = ""
var curr = s[0]
var count = 1
var i = 1
while (i < s.count) {
if (s[i] == curr) {
count = count + 1
} else {
e = e + count.toString + curr
curr = s[i]
count = 1
}
i = i + 1
}
return e + count.toString + curr
}
 
var decode = Fn.new { |e|
if (e == "") return e
var letters = Pattern.matchesText(p.findAll(e))
var numbers = p.splitAll(e)[0..-2].map { |s| Num.fromString(s) }.toList
return (0...letters.count).reduce("") { |acc, i| acc + letters[i]*numbers[i] }.join()
}
 
var strings = [
"AA",
"RROSETTAA",
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
]
 
for (s in strings) {
System.print("Original text : %(s)")
var e = encode.call(s)
System.print("Encoded text : %(e)")
var d = decode.call(e)
System.print("Decoded text : %(d)")
System.print("Original = decoded : %(s == d)\n")
}
</syntaxhighlight>
 
{{out}}
<pre>
Original text : AA
Encoded text : 2A
Decoded text : AA
Original = decoded : true
 
Original text : RROSETTAA
Encoded text : 2R1O1S1E2T2A
Decoded text : RROSETTAA
Original = decoded : true
 
Original text : WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Encoded text : 12W1B12W3B24W1B14W
Decoded text : WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Original = decoded : true
</pre>
 
=={{header|XPL0}}==
<langsyntaxhighlight XPL0lang="xpl0">include c:\cxpl\codes; \intrinsic 'code' declarations
string 0; \use zero-terminated strings, instead of MSb terminated
 
Line 3,189 ⟶ 6,559:
CrLf(0);
Expand("W11BW11B2W23BW13"); CrLf(0);
]</langsyntaxhighlight>
 
Output (with slightly better compression than the example):
Line 3,197 ⟶ 6,567:
</pre>
 
=={{header|BefungeZig}}==
<syntaxhighlight lang="zig">const std = @import("std");
Not the same format as in the example,it puts "n\n" at the beginning so you can pipe the output back in and receive the input.
 
Pipe the output of the program-it's more reliable.
fn Run(comptime T: type) type {
{{works with|CCBI|2.1}}
return struct {
<lang Befunge> ~"y"- ~$ v
value: T,
<temp var for when char changes
length: usize,
format:
};
first,'n' and a newline. :
}
a char then a v _"n",v
 
number then a space continuously 9
fn encode(
example: 1
comptime T: type,
n > v ,+<
input: []const T,
a5 b2
allocator: std.mem.Allocator,
decoded:aaaaabb
) ![]Run(T) {
the program is ended using decoder
var runs = std.ArrayList(Run(T)).init(allocator);
Ctrl-C on linux,or alt-f4
defer runs.deinit();
on windows.copy the output >\v encoder
 
of the program somewhere ^_ $ v
var previous: ?T = null;
to encode press y : > $11g:, v
var length: usize = 0;
to decode pipe file in >1-^ ~ v +1\<
 
the output of the encoder \ v< $ ^ .\_^
for (input) |current| {
starts with n,this is so ^,:<\&~< _~:,>1>\:v>^
if (previous == current) {
you can pipe it straight in ^ <
length += ~1;
} else if (previous) |value| {
the spaces seem to be a annoying thing :
try runs.append(.{
thanks to CCBI...if a interpreter dosen't 1
.value = value,
create them it's non-conforming and thus 1
.length = length,
the validity of this program is NOT affected p-
>^});
previous = current;
--written by Gamemanj,for Rosettacode</lang>
length = 1;
} else {
previous = current;
length += 1;
}
}
 
if (previous) |value| {
try runs.append(.{
.value = value,
.length = length,
});
}
 
return runs.toOwnedSlice();
}
 
test encode {
const input =
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
 
const expected = [_]Run(u8){
.{ .length = 12, .value = 'W' },
.{ .length = 1, .value = 'B' },
.{ .length = 12, .value = 'W' },
.{ .length = 3, .value = 'B' },
.{ .length = 24, .value = 'W' },
.{ .length = 1, .value = 'B' },
.{ .length = 14, .value = 'W' },
};
 
const allocator = std.testing.allocator;
const actual = try encode(u8, input, allocator);
defer allocator.free(actual);
 
try std.testing.expectEqual(expected.len, actual.len);
for (expected, actual) |e, a| {
try std.testing.expectEqual(e.length, a.length);
try std.testing.expectEqual(e.value, a.value);
}
}
 
fn decode(
comptime T: type,
runs: []const Run(T),
allocator: std.mem.Allocator,
) ![]T {
var values = std.ArrayList(T).init(allocator);
defer values.deinit();
for (runs) |r|
try values.appendNTimes(r.value, r.length);
return values.toOwnedSlice();
}
 
test decode {
const runs = [_]Run(u8){
.{ .length = 12, .value = 'W' },
.{ .length = 1, .value = 'B' },
.{ .length = 12, .value = 'W' },
.{ .length = 3, .value = 'B' },
.{ .length = 24, .value = 'W' },
.{ .length = 1, .value = 'B' },
.{ .length = 14, .value = 'W' },
};
 
const allocator = std.testing.allocator;
const decoded = try decode(u8, &runs, allocator);
defer allocator.free(decoded);
 
try std.testing.expectEqualStrings(
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW",
decoded,
);
}
 
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(gpa.deinit() == .ok);
 
const allocator = gpa.allocator();
var input = std.ArrayList(u8).init(allocator);
defer input.deinit();
 
const stdout = std.io.getStdOut().writer();
const stdin = std.io.getStdIn().reader();
try stdout.print("Input: ", .{});
try stdin.streamUntilDelimiter(input.writer(), '\n', null);
 
const runs = try encode(u8, input.items, allocator);
defer allocator.free(runs);
 
try stdout.print("Encoded:\n", .{});
for (runs) |r|
try stdout.print(" {}\n", .{r});
 
const decoded = try decode(u8, runs, allocator);
defer allocator.free(decoded);
 
try stdout.print("Decoded: {s}\n", .{decoded});
}</syntaxhighlight>
{{out}}
<pre>
Input: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Encoded:
run_length_encoding.Run(u8){ .value = 87, .length = 12 }
run_length_encoding.Run(u8){ .value = 66, .length = 1 }
run_length_encoding.Run(u8){ .value = 87, .length = 12 }
run_length_encoding.Run(u8){ .value = 66, .length = 3 }
run_length_encoding.Run(u8){ .value = 87, .length = 24 }
run_length_encoding.Run(u8){ .value = 66, .length = 1 }
run_length_encoding.Run(u8){ .value = 87, .length = 14 }
Decoded: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|zkl}}==
A byte stream to byte stream codec, the streams hard coded for ease. Character '\1' is used as a sentinel and there are limits on the run length to avoid byte overflow.
<syntaxhighlight lang="zkl">const MAX_LEN=250, MIN_LEN=3;
fcn compress(text){ // !empty byte/text stream -->Data (byte stream)
sink:=Data(); cnt:=Ref(0);
write:='wrap(c,n){ // helper function
while(n>MAX_LEN){
sink.write(1); sink.write(MAX_LEN); sink.write(c);
n-=MAX_LEN;
}
if(n>MIN_LEN){ sink.write(1); sink.write(n); sink.write(c); }
else { do(n) { sink.write(c); } }
};
text.reduce('wrap(a,b){
if(a==b) cnt.inc();
else{ write(a,cnt.value); cnt.set(1); }
b
},text[0]) : write(_,cnt.value);
sink;
}</syntaxhighlight>
<syntaxhighlight lang="zkl">fcn inflate(data){ //-->String
data.howza(3).pump(String,
fcn(c){ // if c==1, read n,c2 and expand, else write c
if(c=="\x01") return(Void.Read,2) else return(Void.Write,c) },
fcn(_,n,c){ c*n.toAsc() })
}</syntaxhighlight>
<syntaxhighlight lang="zkl">text:="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
d:=compress(text);
d.bytes().println();
println(text.len()," bytes --> ",d.len()," bytes");
println(text==inflate(d));</syntaxhighlight>
{{out}}
<pre>
L(1,12,87,66,1,12,87,66,66,66,1,24,87,66,1,14,87)
67 bytes --> 17 bytes
True
</pre>
9,482

edits