Run-length encoding: Difference between revisions

m
(→‎Linq: Updated short linq solution to match)
m (→‎{{header|Wren}}: Minor tidy)
 
(104 intermediate revisions by 50 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 62 ⟶ 292:
Put_Line (Encode ("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"));
Put_Line (Decode ("12W1B12W3B24W1B14W"));
end Test_Run_Length_Encoding;</langsyntaxhighlight>
Sample output:
<pre>
Line 77 ⟶ 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 148 ⟶ 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 166 ⟶ 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 202 ⟶ 712:
}
Return output
}</langsyntaxhighlight>
 
=={{header|AWK}}==
Line 211 ⟶ 721:
'''Encoding'''
 
<langsyntaxhighlight lang="awk">BEGIN {
FS=""
}
Line 226 ⟶ 736:
}
printf("%d%c", j, cp)
}</langsyntaxhighlight>
 
'''Decoding'''
 
<langsyntaxhighlight lang="awk">BEGIN {
RS="[0-9]+[^0-9]"
final = "";
Line 242 ⟶ 752:
END {
print final
}</langsyntaxhighlight>
 
=={{header|BaCon}}==
<langsyntaxhighlight lang="qbasic">FUNCTION Rle_Encode$(txt$)
 
LOCAL result$, c$ = LEFT$(txt$, 1)
Line 286 ⟶ 796:
encoded$ = Rle_Encode$(rle_data$)
PRINT "Encoded: ", encoded$
PRINT "Decoded: ", Rle_Decode$(encoded$)</langsyntaxhighlight>
{{out}}
<pre>RLEData: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 299 ⟶ 809:
{{trans|PowerBASIC}}
 
<langsyntaxhighlight lang="qbasic">DECLARE FUNCTION RLDecode$ (i AS STRING)
DECLARE FUNCTION RLEncode$ (i AS STRING)
 
Line 353 ⟶ 863:
outP = outP + tmp2
RLEncode$ = outP
END FUNCTION</langsyntaxhighlight>
 
Sample output (last one shows errors from using numbers in input string):
Line 371 ⟶ 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 409 ⟶ 1,022:
ENDIF
ENDWHILE
= o$</langsyntaxhighlight>
 
=={{header|Befunge}}==
Line 415 ⟶ 1,028:
Pipe the output of the program-it's more reliable.
{{works with|CCBI|2.1}}
<langsyntaxhighlight Befungelang="befunge"> ~"y"- ~$ v
<temp var for when char changes
format:
Line 440 ⟶ 1,053:
the validity of this program is NOT affected p-
>^
--written by Gamemanj,for Rosettacode</langsyntaxhighlight>
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat"> ( run-length
= character otherCharacter acc begin end
. :?acc
Line 464 ⟶ 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 621 ⟶ 1,234:
 
return 0;
}</langsyntaxhighlight>
 
See [[Run-length encoding/C]]
 
=={{header|C++}}==
{{libheader|boost}}
<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( ) ;
}</lang>
 
=={{header|C sharp|C#}}==
=== Linq ===
<!--Martin Freedman 22/02/2018-->
<langsyntaxhighlight lang="csharp">using System.Collections.Generic;
using System.Linq;
using static System.Console;
Line 720 ⟶ 1,277:
}
}
}</langsyntaxhighlight>
Output:
<pre>raw = WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 730 ⟶ 1,287:
 
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.
<langsyntaxhighlight lang="csharp">using System.Collections.Generic;
using System.Linq;
using static System.Console;
Line 759 ⟶ 1,316:
string.Join(",", list.Select(t => $"[{t.i},{t.c}]"));
}
}</langsyntaxhighlight>
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>
Line 770 ⟶ 1,372:
This example only works if there are no digits in the string to be encoded and then decoded.
 
<langsyntaxhighlight lang="csharp"> public static void Main(string[] args)
{
string input = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
Line 818 ⟶ 1,420:
}
return sb.ToString();
}</langsyntaxhighlight>
 
=== RegEx ===
Somewhat shorter, using Regex.Replace with MatchEvaluator (using C#2 syntax only):
<langsyntaxhighlight lang="csharp">using System;
using System.Text.RegularExpressions;
 
Line 858 ⟶ 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 867 ⟶ 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}}
<langsyntaxhighlight lang="cobol"> >>SOURCE FREE
IDENTIFICATION DIVISION.
PROGRAM-ID. run-length-encoding.
Line 994 ⟶ 1,848:
END-PERFORM
.
END FUNCTION decode.</langsyntaxhighlight>
 
{{out}}
Line 1,005 ⟶ 1,859:
=={{header|CoffeeScript}}==
 
<langsyntaxhighlight lang="coffeescript">encode = (str) ->
str.replace /(.)\1*/g, (w) ->
w[0] + w.length
Line 1,015 ⟶ 1,869:
console.log s = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
console.log encode s
console.log decode encode s</langsyntaxhighlight>
 
<pre>
Line 1,025 ⟶ 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 1,032 ⟶ 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 1,044 ⟶ 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 1,066 ⟶ 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 1,082 ⟶ 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.
Line 1,137 ⟶ 1,991:
writeln("Encoded: ", encoded);
assert(txt == encoded.decode);
}</langsyntaxhighlight>
{{out}}
<pre>Input: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 1,145 ⟶ 1,999:
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 1,223 ⟶ 2,077:
auto sEncoded = RLE.init.encode(s).encoded ;
assert(s == RLE(sEncoded).decode(), "Not work");
}</langsyntaxhighlight>
 
output from "display.txt":
Line 1,244 ⟶ 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 1,275 ⟶ 2,129:
"11#222##333";
assert(s == reDecode(reEncode(s)));
}</langsyntaxhighlight>
 
=={{header|Déjà Vu}}==
<langsyntaxhighlight lang="dejavu">rle:
if not dup:
drop
Line 1,306 ⟶ 2,160:
rle "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
!. dup
!. rld</langsyntaxhighlight>
{{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,340 ⟶ 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|Elena}}==
ELENA 3.3 :
<lang elena>import system'text.
import system'routines.
import extensions.
 
=={{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
{
literalstring compress(literalstring s)
[{
type<TextBuilder>auto tb := TextBuilder 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 := 1tb.writeFormatted("{0}{1}",count,current);
count := 1;
current := ch
]}
].};
tb .writeFormatted("{0}{1}",count,current).;
^ tb
]}
literalstring decompress(literalstring s)
[{
type<TextBuilder>auto tb := new TextBuilder new.();
char current := $0.;
var a := String new. StringWriter();
s .forEach(::(ch)
[{
current := ch.;
if (current .isDigit())
[{
a .append(ch)
];}
[else
int count := a toInt.{
aint clearcount := a.toInt();
a.clear();
tb fill(current,count).
] tb.fill(current,count)
]. }
};
^ tb
]}
}
 
public program()
program =
{
[
var s := "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW".;
s := compressor .compress(s).;
console .printLine(s).;
s := compressor .decompress(s).;
console .printLine(s).
}</syntaxhighlight>
].</lang>
{{out}}
<pre>
Line 1,419 ⟶ 2,420:
 
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">defmodule Run_length do
def encode(str) when is_bitstring(str) do
to_char_list(str) |> encode |> to_string
Line 1,445 ⟶ 2,446:
|> Run_length.encode |> IO.inspect
|> Run_length.decode |> IO.inspect
end)</langsyntaxhighlight>
 
{{out}}
Line 1,457 ⟶ 2,458:
'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,462 ⟶ 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,507 ⟶ 2,529:
?_assert(decode(Expected) =:= PreEncoded),
?_assert(decode(encode(PreEncoded)) =:= PreEncoded)
].</langsyntaxhighlight>
 
A version that works on character lists:
 
<langsyntaxhighlight lang="erlang">
-module(rle).
 
Line 1,532 ⟶ 2,554:
decode([{Count, Char}|T], Acc) ->
decode(T, [[Char || _ <- lists:seq(1, Count)]|Acc]).
</syntaxhighlight>
</lang>
 
=={{header|Euphoria}}==
<langsyntaxhighlight lang="euphoria">include misc.e
 
function encode(sequence s)
Line 1,572 ⟶ 2,594:
pretty_print(1,s,{3})
puts(1,'\n')
puts(1,decode(s))</langsyntaxhighlight>
 
Output:
Line 1,579 ⟶ 2,601:
 
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
open System
open System.Text.RegularExpressions
Line 1,598 ⟶ 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,652 ⟶ 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,669 ⟶ 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,751 ⟶ 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]'''
<langsyntaxhighlight lang="gambas">Public Sub Main()
Dim sString As String = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
Dim siCount As Short = 1
Line 1,777 ⟶ 2,971:
Print sString & gb.NewLine & sHold.Join(", ")
 
End</langsyntaxhighlight>
Output:
<pre>
Line 1,786 ⟶ 2,980:
=={{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,856 ⟶ 3,050:
}
return string(d)
}</langsyntaxhighlight>
Output:
<pre>
Line 1,866 ⟶ 3,060:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def rleEncode(text) {
def encoded = new StringBuilder()
(text =~ /(([A-Z])\2*)/).each { matcher ->
Line 1,880 ⟶ 3,074:
}
decoded.toString()
}</langsyntaxhighlight>
Test code
<langsyntaxhighlight lang="groovy">def text = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
def rleEncoded = rleEncode(text)
assert rleEncoded == '12W1B12W3B24W1B14W'
Line 1,888 ⟶ 3,082:
 
println "Original Text: $text"
println "Encoded Text: $rleEncoded"</langsyntaxhighlight>
Output:
<pre>Original Text: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 1,894 ⟶ 3,088:
 
=={{header|Haskell}}==
===VersionIn 1terms of group===
<langsyntaxhighlight lang="haskell">import Data.List (group)
import Control.Arrow ((&&&))
 
-- 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 ((,) <$> length &&&<*> head) . group
 
-- Takes an encoded list of tuples and returns the associated decoded String
Line 1,912 ⟶ 3,106:
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}}
===Version 2===
<pre>Encoded: [(12,'W'),(1,'B'),(12,'W'),(3,'B'),(24,'W'),(1,'B'),(14,'W')]
<lang Haskell>
Decoded: "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"</pre>
import Data.List
import Data.Char
 
Or:
runLengthEncode = concatMap (\xs@(x:_) -> (show.length $ xs) ++ [x]).group
<syntaxhighlight lang="haskell">import Data.Char (isDigit)
runLengthDecode = concat.uncurry (zipWith (\[x] ns -> replicate (read ns) x))
import Data.List (group, groupBy)
.foldr (\z (x,y) -> (y,z:x)) ([],[]).groupBy (\x y -> all isDigit [x,y])
 
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"
let encode = runLengthEncode text
let decode = runLengthDecode encode
mapM_ putStrLn [text, encode, decode]
putStrLn $ "test: text == decode => " ++<> (show $ (text == decode)</syntaxhighlight>
</lang>
{{out}}
<pre>WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
<pre>
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
test: text == decode => True</pre>
 
</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,970 ⟶ 3,237:
procedure Repl(n, c)
return repl(c,n)
end</langsyntaxhighlight>
 
Sample output:
Line 1,980 ⟶ 3,247:
=={{header|J}}==
'''Solution:'''
<langsyntaxhighlight lang="j">rle=: ;@(<@(":@(#-.1:),{.);.1~ 1, 2 ~:/\ ])
rld=: ;@(-.@e.&'0123456789' <@({:#~1{.@,~".@}:);.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.
Line 2,000 ⟶ 3,267:
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]):
 
<langsyntaxhighlight lang="j"> torle=: (#, {.);.1~ 1,2 ~:/\ ]
frle=: #/@|:</langsyntaxhighlight>
 
Task example:
 
<langsyntaxhighlight lang="j"> torle a.i.'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
12 87
1 66
Line 2,014 ⟶ 3,281:
14 87
u: frle torle a.i.'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</langsyntaxhighlight>
 
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 2,056 ⟶ 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 2,091 ⟶ 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 2,109 ⟶ 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>
 
===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
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}}==
Line 2,129 ⟶ 3,505:
 
'''Utility function:'''
<langsyntaxhighlight lang="jq">def runs:
reduce .[] as $item
( [];
Line 2,137 ⟶ 3,513:
else . + [[$item, 1]]
end
end ) ;</langsyntaxhighlight>
'''Run-length encoding and decoding''':
<langsyntaxhighlight lang="jq">def run_length_encode:
explode | runs | reduce .[] as $x (""; . + "\($x[1])\([$x[0]]|implode)");
 
Line 2,147 ⟶ 3,523:
($pair[0:-1] | tonumber) as $n
| $pair[-1:] as $letter
| . + ($n * $letter)) ;</langsyntaxhighlight>
'''Example''':
<langsyntaxhighlight lang="jq">"ABBCCC" | run_length_encode | run_length_decode</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="sh">$ jq -n -f Run_length_encoding.jq
"ABBCCC"</langsyntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">using IterTools
 
encode(str::String) = collect((length(g), first(g)) for g in groupby(first, str))
Line 2,166 ⟶ 3,542:
decoded = decode(encoded)
println("Original: $original\n -> encoded: $encoded\n -> decoded: $decoded")
end</langsyntaxhighlight>
 
{{out}}
Line 2,178 ⟶ 3,554:
=={{header|K}}==
 
<langsyntaxhighlight lang="k">rle: {,/($-':i,#x),'x@i:&1,~=':x}</langsyntaxhighlight>
 
{{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
<langsyntaxhighlight lang="scala">tailrec fun runLengthEncoding(text:String,prev:String=""):String {
if (text.isEmpty()){
return prev
Line 2,206 ⟶ 3,582:
assert(runLengthEncoding("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
== "12W1B12W3B24W1B14W")
}</langsyntaxhighlight>
 
=={{header|Lasso}}==
<langsyntaxhighlight Lassolang="lasso">define rle(str::string)::string => {
local(orig = #str->values->asCopy,newi=array, newc=array, compiled=string)
while(#orig->size) => {
Line 2,255 ⟶ 3,631:
 
rlde('12W1B12W3B24W1B14W')
rlde('1d1s1f1k1j2h1k1d1s1j1f1h1d1s1k1h1s1h1d2j1f2h1d1l1s2l1w')</langsyntaxhighlight>
 
{{out}}
Line 2,266 ⟶ 3,642:
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">mainwin 100 20
 
'In$ ="aaaaaaaaaaaaaaaaaccbbbbbbbbbbbbbbba" ' testing...
Line 2,313 ⟶ 3,689:
next i
Decoded$ =r$
end function</langsyntaxhighlight>
 
=={{header|LiveCode}}==
<langsyntaxhighlight LiveCodelang="livecode">function rlEncode str
local charCount
put 1 into charCount
Line 2,358 ⟶ 3,734:
end repeat
return repStr
end repeatString</langsyntaxhighlight>
 
 
=={{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 2,379 ⟶ 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 2,413 ⟶ 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}}
RunLengthDecode[s_String] := StringJoin[
<pre style="height:30ex;overflow:scroll">
Table[#[[2]], {ToExpression[#[[1]]]}] & /@
Input: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Partition[StringSplit[s, x : _?LetterQ :> x], 2]
RLE Encoded: 12W1B12W3B24W1B14W
]</lang>
RLE Decoded: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
This second encode function is adapted from the MathWorld example.
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>
 
=={{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 2,446 ⟶ 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 2,560 ⟶ 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
Line 2,568 ⟶ 4,014:
=={{header|Nim}}==
{{trans|Python}}
<langsyntaxhighlight lang="nim">import parseutils, strutils
 
proc compress(input: string): string =
type RunLength = tuple[c: char, n: int]
var
count = 1
prev = '\0'
 
for ch in input:
proc encode(inp): seq[RunLength] =
result if ch != @[]prev:
if prev != '\0':
var count = 1
result.add $count & prev
var prev: char
 
for c in inp:
if c != prev:
if prev != chr(0):
result.add((prev,count))
count = 1
prev = cch
else:
inc( count)
result.add((prev, $count)) & prev
 
proc decodeuncompress(lsttext: openarray[RunLength]string): string =
resultvar start = ""0
var count: int
for x in lst:
while true:
result.add(repeatChar(x.n, x.c))
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
 
 
echo encode("aaaaahhhhhhmmmmmmmuiiiiiiiaaaaaa")
const Text = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
echo decode([('a', 5), ('h', 6), ('m', 7), ('u', 1), ('i', 7), ('a', 6)])</lang>
 
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}}==
<langsyntaxhighlight lang="objeck">use RegEx;
 
class RunLengthEncoding {
Line 2,647 ⟶ 4,108:
return output;
}
}</langsyntaxhighlight>
 
<pre>encoding: 12W1B12W3B24W1B14W
Line 2,657 ⟶ 4,118:
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">let encode str =
let len = String.length str in
let rec aux i acc =
Line 2,679 ⟶ 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 2,687 ⟶ 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 2,706 ⟶ 4,167:
let () =
print_endline (encode "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW");
print_endline (decode "12W1B12W3B24W1B14W");</langsyntaxhighlight>
 
=={{header|Oforth}}==
 
<langsyntaxhighlight Oforthlang="oforth">: encode(s)
StringBuffer new
s group apply(#[ tuck size asString << swap first <<c ]) ;
Line 2,721 ⟶ 4,182:
loop: i [ c <<c ] 0
]
drop ;</langsyntaxhighlight>
 
{{out}}
Line 2,733 ⟶ 4,194:
</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 2,770 ⟶ 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 2,802 ⟶ 4,304:
};
rle("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
elr(%)</langsyntaxhighlight>
Output:
<pre>%1 = "12W1B12W3B24W1B14W"
Line 2,809 ⟶ 4,311:
 
=={{header|Pascal}}==
<langsyntaxhighlight lang="pascal">Program RunLengthEncoding(output);
procedure encode(s: string; var counts: array of integer; var letters: string);
Line 2,859 ⟶ 4,361:
decode(s, counts, letters);
writeln(s);
end.</langsyntaxhighlight>
Output:
<pre>:> ./RunLengthEncoding
Line 2,871 ⟶ 4,373:
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):
 
<langsyntaxhighlight lang="perl">sub encode {
shift =~ s/(.)\1*/length($&).$1/grse;
}
Line 2,877 ⟶ 4,379:
sub decode {
shift =~ s/(\d+)(.)/$2 x $1/grse;
}</langsyntaxhighlight>
 
Modified version that can take arbitrary byte strings as input (produces encoded byte strings that are compatible with the [[#C|C solution]]):
 
<langsyntaxhighlight lang="perl">sub encode {
shift =~ s/(.)\1{0,254}/pack("C", length($&)).$1/grse;
}
Line 2,887 ⟶ 4,389:
sub decode {
shift =~ s/(.)(.)/$2 x unpack("C", $1)/grse;
}</langsyntaxhighlight>
 
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):
 
<langsyntaxhighlight lang="perl">sub encode {
my $str = shift;
my $ret = "";
Line 2,922 ⟶ 4,424:
}
return $ret;
}</langsyntaxhighlight>
 
Demonstration of the third version:
 
<langsyntaxhighlight lang="perl">use Data::Dump qw(dd);
dd my $str = "XXXXXABCDEFGHIoooooooooooooooooooooooooAAAAAA";
dd my $enc = encode($str);
dd decode($enc);</langsyntaxhighlight>
 
{{out}}
Line 2,937 ⟶ 4,439:
"XXXXXABCDEFGHIoooooooooooooooooooooooooAAAAAA"
</pre>
 
=={{header|Perl 6}}==
Note that Perl 6 regexes don't care about unquoted whitespace, and that backrefs
count from 0, not from 1.
 
<lang perl6>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);</lang>
 
Output:
 
<pre>12W1B12W3B24W1B14W
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW</pre>
 
=={{header|Phix}}==
CopyBased ofon [[Run-length_encoding#Euphoria|Euphoria]], but uses a few string in place of sequence.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function encode(sequence s)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
sequence out = {}
<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>
integer prev_char,count = 1
<span style="color: #004080;">sequence</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
if length(s) then
<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>
prev_char = s[1]
<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>
for i=2 to length(s) do
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
if s[i]!=prev_char then
<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>
out &= {count,prev_char}
<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>
prev_char = s[i]
<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>
count = 1
<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>
else
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
count += 1
end if<span style="color: #008080;">else</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
out &= {count,prev_char}
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end if
<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>
return out
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function decode(sequence s)
sequence out = {}
<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>
for i=1 to length(s) by 2 do
<span style="color: #004080;">string</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
out &= repeat(s[i+1],s[i])
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">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>
end for
<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>
return out
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence s = encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
pp(s)
<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>
?decode(s)</lang>
<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'}
Line 2,994 ⟶ 4,483:
 
=={{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 3,030 ⟶ 4,618:
(prinl "Data: " "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW")
(prinl "Encoded: " (encode @))
(prinl "Decoded: " (decode @)) )</langsyntaxhighlight>
Output:
<pre>Data: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 3,037 ⟶ 4,625:
 
=={{header|PL/I}}==
<langsyntaxhighlight lang="pli">declare (c1, c2) character (1);
declare run_length fixed binary;
declare input file;
Line 3,074 ⟶ 4,662:
end;
put edit ((c do i = 1 to run_length)) (a);
end;</langsyntaxhighlight>
 
=={{header|PowerBASIC}}==
Line 3,080 ⟶ 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 3,131 ⟶ 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 3,153 ⟶ 4,741:
}
return $ret
}</langsyntaxhighlight>
Output:
<pre>PS> Compress-RLE "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
Line 3,159 ⟶ 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 3,269 ⟶ 4,858:
 
run(Var,[Other|RRest], [1,Var],[Other|RRest]):-
dif(Var,Other).</langsyntaxhighlight>
Output :
<pre> ?- run_length.
Line 3,281 ⟶ 4,870:
 
=={{header|Pure}}==
<langsyntaxhighlight lang="pure">using system;
 
encode s = strcat $ map (sprintf "%d%s") $ encode $ chars s with
Line 3,295 ⟶ 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 3,364 ⟶ 4,953:
Input()
CloseConsole()
EndIf</langsyntaxhighlight>
Sample output:
<pre>Type something: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWW
Line 3,373 ⟶ 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 3,388 ⟶ 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 3,413 ⟶ 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 3,438 ⟶ 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 lang="rsplus">runlengthencoding <- function(x)
{
splitx <- unlist(strsplit(input, ""))
Line 3,450 ⟶ 5,075:
 
input <- "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
runlengthencoding(input)</langsyntaxhighlight>
Similarly, inverse.rle provides decompression after a run length encoding.
<langsyntaxhighlight lang="rsplus">inverserunlengthencoding <- function(x)
{
lengths <- as.numeric(unlist(strsplit(output, "[[:alpha:]]")))
Line 3,462 ⟶ 5,087:
 
output <- "12W1B12W3B24W1B14W"
inverserunlengthencoding(output)</langsyntaxhighlight>
 
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
(define (encode str)
Line 3,472 ⟶ 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}}==
Line 3,478 ⟶ 5,121:
The task (input) rule was relaxed a bit as this program accepts upper─ and lowercase input.
 
An error message is generated if the input text is invalid.
Note that this REXX version (for encoding and decoding) uses a &nbsp; ''replication'' &nbsp; count, not the &nbsp; ''count'' &nbsp; of characters,
<br>so a replication count of &nbsp; '''11''' &nbsp; represents a count of &nbsp; '''12''' &nbsp; characters.
====encoding====
<lang rexx>/*REXX program encodes a string by using a run─length encoding scheme. */
parse arg x . /*normally, input would be in a file. */
def= 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
if x='' then x=def /*Input not specified? Then use default*/
Lx=length(x) /*get the length of the X string. */
y= /*Y: is the output string (so far). */
do j=1 by 0 to Lx /*J: is incremented within the loop. */
c=substr(x,j,1) /*pick a character, check for an error.*/
if \datatype(c,'M') then do; say "error!: data isn't alphabetic:" c; exit 13; end
r=0 /*R: is NOT the number of characters. */
do k=j+1 to Lx while substr(x,k,1)==c; r=r+1
end /*k*/ /*R: is a replication count for a char*/
j=j+1+r /*increment (add to) the DO loop index.*/
if r==0 then r= /*don't use R if it is equal to zero.*/
Y = Y || r || c /*add character to the encoded string. */
end /*j*/
 
In addition, a &nbsp;''yay''&nbsp; or &nbsp;''nay''&nbsp; message is also displayed if the decoding of the encoding was successful.
say ' input=' x
say 'encoded=' y /*stick a fork in it, we're all done. */</lang>
'''output''' when using the default input:
<pre>
input= WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
output= 11WB11W2B23WB13W
</pre>
 
Note that this REXX version (for encoding and decoding) uses a &nbsp; ''replication'' &nbsp; count, not the &nbsp; ''count'' &nbsp; of characters,
====decoding====
<br>so a replication count of &nbsp; '''11''' &nbsp; represents a count of &nbsp; '''12''' &nbsp; characters.
<lang rexx>/*REXX program decodes a string by using a run─length decoding scheme. */
<syntaxhighlight lang="rexx">/*REXX program encodes and displays a string by using a run─length encoding scheme. */
parse arg x . /*normally, input would be in a file. */
parse arg input . /*normally, input would be in a file. */
if x=='' then x=11WB11W2B23WB13W /*X not specified? Then use default.*/
default= 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
Lx=length(x) /*get the length of the input string. */
if input=='' | input=="," then input= default /*Not specified? Then use the default.*/
y= /*Y: is the output string (so far). */
do jencode=1 by 0 to Lx RLE(input) ; say ' input=' input /*warning!encode input Jstring; isdisplay modifiedinput. within loop.*/
say 'encoded=' encode /* display run─len*/
c=substr(x,j,1)
decode= RLD(encode); say 'decoded=' decode /*decode the run─len; display decode.*/
if \datatype(c,'W') then do /*a loner char, simply add to output. */
if decode==input then say 'OK'; else say "¬ OK" /*display yay or nay (success/failure).*/
y=y || c; j=j+1; iterate /*j*/
exit 0 end /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
d=1 /* [↓] W: a Whole number.*/
err: say; say "***error*** input data isn't alphabetic:" c; say; exit 13
do k=j+1 to Lx while datatype(substr(x,k,1),'w'); d=d+1 /*end of #?*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
end /*k*/ /*D: is the number of characters so far*/
RLE: procedure; parse arg x; $= /*$: is the output string (so far). */
 
n=substr(x,j,d)+1 /*D: isLx= length(x) /*get length of the encodedplain text numberstring. */
y do j=y1 || copies(by 0 to Lx; c= substr(x,k j, 1), n) /*N:obtain a ischaracter nowfrom theplain numbertext. of characters. */
j=j+1+d if \datatype(c, 'M') then call err /*incrementCharacter thenot DOa loopletter? index byIssue D+1error. */
r= 0 /*R: is NOT the number of characters. */
end /*j*/
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*/
say ' input=' x
say 'decoded=' y end /*stick a fork in it, we're all done. k*/</lang>
j= j + r + 1 /*increment (add to) the DO loop index.*/
'''output''' when using the default input:
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
input= 11WB11W2B23WB13W
encoded= 11WB11W2B23WB13W
decoded= WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
===version 2===
<syntaxhighlight lang="rexx">
<lang rexx>s='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
/*REXX*/
s='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
Say ' s='s
enc=encode(s)
Line 3,573 ⟶ 5,213:
 
o: ol=ol||arg(1)
Return</langsyntaxhighlight>
{{out}}
<pre> s=WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 3,582 ⟶ 5,222:
===version 3===
No need to output counts that are 1
<syntaxhighlight lang="rexx">
<lang rexx>s='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
/*REXX*/
s='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'
Say ' s='s
enc=encode(s)
Line 3,629 ⟶ 5,271:
 
o: ol=ol||arg(1)
Return</langsyntaxhighlight>
{{out}}
<pre> s=WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
Line 3,637 ⟶ 5,279:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Run-length encoding
# Date : 2017/12/04
# Author : Gal Zsolt (~ CalmoSoft ~)
# Email : <calmosoft@gmail.com>
 
load "stdlib.ring"
Line 3,668 ⟶ 5,307:
see dec
next
</syntaxhighlight>
</lang>
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>
 
Line 3,681 ⟶ 5,353:
Ruby has built-in run-length encoding in the form of <code>chunk</code>, here I provide a thin wrapper around it:
 
<langsyntaxhighlight lang="ruby">
# run_encode("aaabbbbc") #=> [["a", 3], ["b", 4], ["c", 1]]
def run_encode(string)
Line 3,697 ⟶ 5,369:
end
 
</syntaxhighlight>
</lang>
 
<langsyntaxhighlight lang="ruby">def encode(string)
string.scan(/(.)(\1*)/).collect do |char, repeat|
[1 + repeat.length, char]
Line 3,707 ⟶ 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 3,720 ⟶ 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 3,730 ⟶ 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 3,746 ⟶ 5,418:
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">string$ = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
beg = 1
i = 1
Line 3,771 ⟶ 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 3,790 ⟶ 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 3,815 ⟶ 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 3,846 ⟶ 5,587:
s/^([0-9]+.)(.*)/\2\1/
b start
</syntaxhighlight>
</lang>
 
The decode script:
<langsyntaxhighlight lang="sed">
/^$/ b
:start
Line 3,871 ⟶ 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 3,883 ⟶ 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 3,921 ⟶ 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:
<langsyntaxhighlight lang="ruby">func encode(str) {
str.gsub(/((.)(\2*))/, {|a,b| "#{a.len}#{b}" });
}
Line 3,931 ⟶ 5,708:
func decode(str) {
str.gsub(/(\d+)(.)/, {|a,b| b * a.to_i });
}</langsyntaxhighlight>
{{out}}
<pre>12W1B12W3B24W1B14W</pre>
 
Second solution, encoding the length into a byte:
<langsyntaxhighlight lang="ruby">func encode(str) {
str.gsub(/(.)(\1{0,254})/, {|a,b| b.len+1 -> chr + a});
}
Line 3,947 ⟶ 5,724:
}
return r;
}</langsyntaxhighlight>
{{out}}
<pre>"\fW\1B\fW\3B\30W\1B\16W"</pre>
Line 3,953 ⟶ 5,730:
=={{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 3,960 ⟶ 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 3,978 ⟶ 5,807:
str = rle(str); output = str
str = elr(str); output = str
end</langsyntaxhighlight>
 
Output:
Line 3,984 ⟶ 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 3,989 ⟶ 5,900:
<br>
* RLE encoding
<syntaxhighlight lang="sql">
<lang SQL>
-- variable table
drop table if exists var;
Line 4,037 ⟶ 5,948:
where noWithinGroup = 1
) Rle_Compressed
</syntaxhighlight>
</lang>
 
* RLE decoding
<syntaxhighlight lang="sql">
<lang SQL>
-- variable table
DROP TABLE IF EXISTS var;
Line 4,103 ⟶ 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 4,122 ⟶ 6,033:
 
fun decode lst =
concat (map (fn (c,n) => implode (List.tabulate (n, fn _ => c))) lst)</langsyntaxhighlight>
Example:
<pre>
Line 4,134 ⟶ 6,045:
=={{header|Swift}}==
Using array as the internal representation of the encoded input:
<langsyntaxhighlight lang="swift">import Foundation
 
// "WWWBWW" -> [(3, W), (1, B), (2, W)]
Line 4,148 ⟶ 6,059:
return encoded.reduce("") { $0 + String(count: $1.0, repeatedValue: $1.1) }
}
</syntaxhighlight>
</lang>
 
'''Usage:'''
 
<langsyntaxhighlight lang="swift">
let input = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
let output = decode(encode(input))
print(output == input)
</syntaxhighlight>
</lang>
 
{{Out}}
Line 4,164 ⟶ 6,075:
Converting encoded array into the string and then decoding it using NSScanner:
 
<langsyntaxhighlight lang="swift">// "3W1B2W" -> "WWWBWW"
func decode(encoded: String) -> String {
let scanner = NSScanner(string: encoded)
Line 4,179 ⟶ 6,090:
return out
}
</syntaxhighlight>
</lang>
 
<langsyntaxhighlight lang="swift">let encodedString = encode(input).reduce("") { $0 + "\($1.0)\($1.1)" }
print(encodedString)
let outputString = decode(encodedString)
print(outputString == input)
</syntaxhighlight>
</lang>
 
{{Out}}
Line 4,195 ⟶ 6,106:
=={{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 4,209 ⟶ 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 4,229 ⟶ 6,235:
PRINT input
PRINT output
</syntaxhighlight>
</lang>
Output:
<pre>
Line 4,235 ⟶ 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 4,240 ⟶ 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 4,255 ⟶ 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 4,267 ⟶ 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 4,297 ⟶ 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 4,340 ⟶ 6,559:
CrLf(0);
Expand("W11BW11B2W23BW13"); CrLf(0);
]</langsyntaxhighlight>
 
Output (with slightly better compression than the example):
Line 4,346 ⟶ 6,565:
W11BW11B2W23BW13
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
</pre>
 
=={{header|Zig}}==
<syntaxhighlight lang="zig">const std = @import("std");
 
fn Run(comptime T: type) type {
return struct {
value: T,
length: usize,
};
}
 
fn encode(
comptime T: type,
input: []const T,
allocator: std.mem.Allocator,
) ![]Run(T) {
var runs = std.ArrayList(Run(T)).init(allocator);
defer runs.deinit();
 
var previous: ?T = null;
var length: usize = 0;
 
for (input) |current| {
if (previous == current) {
length += 1;
} else if (previous) |value| {
try runs.append(.{
.value = value,
.length = length,
});
previous = current;
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.
<langsyntaxhighlight lang="zkl">const MAX_LEN=250, MIN_LEN=3;
fcn compress(text){ // !empty byte/text stream -->Data (byte stream)
sink:=Data(); cnt:=Ref(0);
Line 4,367 ⟶ 6,730:
},text[0]) : write(_,cnt.value);
sink;
}</langsyntaxhighlight>
<langsyntaxhighlight 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() })
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">text:="WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
d:=compress(text);
d.bytes().println();
println(text.len()," bytes --> ",d.len()," bytes");
println(text==inflate(d));</langsyntaxhighlight>
{{out}}
<pre>
9,482

edits