I'm trying to count duplicated letters on a String in Elixir. I did try some attempts, but no success until now.
Let's take this string as example: "AAABBAAC"
The desired output would be "3A2B2A1C".
Converting this string to a List, I was able to count every letter, resulting in "5A2B1C", but I have to count following the order.
This is the code I was doing:
string
|> String.graphemes
|> Enum.reduce([], fn(letter, acc) -> Keyword.update(acc, letter, 1, &(&1 + 1)) end)
But, in my tests, I'm trying to produce a List, like this ["AAA", "BB", "AA", "C"], so I can easely count with String.lenght.
Looks like using Enum.chunk_by I'm getting closer to a solution.
Is there a way to produce this?
If you implement this using a recursive approach, you can easily keep track of the last occurred character and its current count, as well an accumulator that holds the result so far. If the current character equals the last character you just increase the count. If the two differ, you add the last character and its count to the accumulator and proceed with the next character until the string is empty. Finally, you encode the final value and return the result.
defmodule RunLengthEncoding do
# public interface, take first char and remember it as the current value
def encode(<<char::utf8, rest::binary>>) do
do_encode(rest, char, 1, "")
end
# current == last, increase the count and proceed
defp do_encode(<<char::utf8, rest::binary>>, char, count, acc) do
do_encode(rest, char, count + 1, acc)
end
# current != last, reset count, encode previous values and proceed
defp do_encode(<<char::utf8, rest::binary>>, last, count, acc) do
do_encode(rest, char, 1, acc <> to_string(count) <> <<last::utf8>>)
end
# input empty, encode final values and return
defp do_encode("", last, count, acc) do
acc <> to_string(count) <> <<last::utf8>>
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With