run-length-encoder
This commit is contained in:
46
elixir/run-length-encoding/lib/run_length_encoder.ex
Normal file
46
elixir/run-length-encoding/lib/run_length_encoder.ex
Normal file
@@ -0,0 +1,46 @@
|
||||
defmodule RunLengthEncoder do
|
||||
@digits ~w(0 1 2 3 4 5 6 7 8 9)
|
||||
|
||||
defguardp is_digit(char) when char in @digits
|
||||
|
||||
defp encode_reducer(char, []), do: [{char, 1}]
|
||||
defp encode_reducer(char, [{char, count} | rest]), do: [{char, count + 1} | rest]
|
||||
defp encode_reducer(char, rest), do: [{char, 1} | rest]
|
||||
|
||||
defp encode_mapper({char, 1}), do: char
|
||||
defp encode_mapper({char, count}), do: "#{count}#{char}"
|
||||
|
||||
defp decode_reducer(digit, []) when is_digit(digit), do: [{nil, digit}]
|
||||
defp decode_reducer(digit, [{nil, count} | rest]) when is_digit(digit), do: [{nil, count <> digit} | rest]
|
||||
defp decode_reducer(char, [{nil, count} | rest]) when not is_digit(char), do: [{char, String.to_integer(count)} | rest]
|
||||
defp decode_reducer(digit, rest) when is_digit(digit), do: [{nil, digit} | rest]
|
||||
defp decode_reducer(char, rest), do: [{char, 1} | rest]
|
||||
|
||||
defp decode_mapper({char, 1}), do: char
|
||||
defp decode_mapper({char, count}), do: String.duplicate(char, count)
|
||||
|
||||
@doc """
|
||||
Generates a string where consecutive elements are represented as a data value and count.
|
||||
"AABBBCCCC" => "2A3B4C"
|
||||
For this example, assume all input are strings, that are all uppercase letters.
|
||||
It should also be able to reconstruct the data into its original form.
|
||||
"2A3B4C" => "AABBBCCCC"
|
||||
"""
|
||||
@spec encode(String.t()) :: String.t()
|
||||
def encode(string) do
|
||||
string
|
||||
|> String.graphemes()
|
||||
|> Enum.reduce([], &encode_reducer/2)
|
||||
|> Enum.reverse()
|
||||
|> Enum.map_join(&encode_mapper/1)
|
||||
end
|
||||
|
||||
@spec decode(String.t()) :: String.t()
|
||||
def decode(string) do
|
||||
string
|
||||
|> String.graphemes()
|
||||
|> Enum.reduce([], &decode_reducer/2)
|
||||
|> Enum.reverse()
|
||||
|> Enum.map_join(&decode_mapper/1)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user