mirror of
https://github.com/correl/elm.git
synced 2024-12-22 11:09:08 +00:00
64 lines
1.4 KiB
Text
64 lines
1.4 KiB
Text
|
module RunLengthEncoding (encode, decode) where
|
||
|
|
||
|
import String exposing (fromChar)
|
||
|
import List exposing (head, tail)
|
||
|
import Maybe exposing (withDefault)
|
||
|
import Regex
|
||
|
|
||
|
{-
|
||
|
To the unaware: this was written by a very green elmer, so don't consider
|
||
|
it an idiomatic exemplar to emulate.
|
||
|
-}
|
||
|
|
||
|
encode : String -> String
|
||
|
encode string =
|
||
|
String.toList string
|
||
|
|> List.foldr countChars []
|
||
|
|> List.map stringifyCounts
|
||
|
|> String.join ""
|
||
|
|
||
|
|
||
|
countChars : a -> List ( number, a ) -> List ( number, a )
|
||
|
countChars current counted =
|
||
|
case head counted of
|
||
|
Just ( count, previous ) ->
|
||
|
if previous == current then
|
||
|
( count + 1, current ) :: withDefault [] (tail counted)
|
||
|
else
|
||
|
( 1, current ) :: counted
|
||
|
|
||
|
Nothing ->
|
||
|
[ ( 1, current ) ]
|
||
|
|
||
|
|
||
|
stringifyCounts : ( number, Char ) -> String
|
||
|
stringifyCounts ( count, char ) =
|
||
|
if count > 1 then
|
||
|
toString count ++ fromChar char
|
||
|
else
|
||
|
fromChar char
|
||
|
|
||
|
|
||
|
decode : String -> String
|
||
|
decode string =
|
||
|
string
|
||
|
|> Regex.find Regex.All (Regex.regex "(\\d+)|(\\D)")
|
||
|
|> List.map .match
|
||
|
|> List.foldl expandCounts ( "", Nothing )
|
||
|
|> fst
|
||
|
|
||
|
|
||
|
expandCounts : String -> ( String, Maybe Int ) -> ( String, Maybe Int )
|
||
|
expandCounts match ( result, count ) =
|
||
|
case count of
|
||
|
Just number ->
|
||
|
( result ++ String.repeat number match, Nothing )
|
||
|
|
||
|
Nothing ->
|
||
|
case String.toInt match of
|
||
|
Ok number ->
|
||
|
( result, Just number )
|
||
|
|
||
|
Err _ ->
|
||
|
( result ++ match, Nothing )
|